efl-js: JavaScript Eolian binding
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>
Mon, 1 Sep 2014 18:08:49 +0000 (15:08 -0300)
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>
Thu, 24 Dec 2015 01:59:40 +0000 (23:59 -0200)
To configure efl sources with bindings to use in nodejs add ––with-js=nodejs in configure flags to generate node files

$ configure --with-js=nodejs

and compile normally with:

$ make
$ make install

To use, you have to require efl:

efl = require('efl')

The bindings is divided in two parts: generated and manually
written. The generation uses the Eolian library for parsing Eo files
and generate C++ code that is compiled against V8 interpreter library
to create a efl.node file that can be required in a node.js instance.

@feature

141 files changed:
.gitignore
Makefile.am
configure.ac
pc/.gitignore
pc/efl-js.pc.in [new file with mode: 0644]
pc/eina-js.pc.in [new file with mode: 0644]
pc/eo-js.pc.in [new file with mode: 0644]
pc/eolian-js.pc.in [new file with mode: 0644]
pc/evas.pc.in
src/Makefile.am
src/Makefile_Ecore.am
src/Makefile_Ecore_Audio.am
src/Makefile_Ecore_Con.am
src/Makefile_Ecore_Js.am [new file with mode: 0644]
src/Makefile_Edje.am
src/Makefile_Efl.am
src/Makefile_Efl_Js.am [new file with mode: 0644]
src/Makefile_Eina_Cxx.am
src/Makefile_Emotion.am
src/Makefile_Eo.am
src/Makefile_Eolian_Js.am [new file with mode: 0644]
src/Makefile_Eolian_Js_Helper.am [new file with mode: 0644]
src/Makefile_Evas.am
src/bin/efl_js/efljslaunch [new file with mode: 0755]
src/bin/efl_js/efljslaunch.desktop [new file with mode: 0644]
src/bin/efl_js/efljslaunch.xml [new file with mode: 0644]
src/bin/efl_js/efljspack [new file with mode: 0755]
src/bin/efl_js/launcher_main.cc [new file with mode: 0644]
src/bin/eolian_js/.gitignore [new file with mode: 0644]
src/bin/eolian_js/eolian/class.hh [new file with mode: 0644]
src/bin/eolian_js/eolian/js/domain.hh [new file with mode: 0644]
src/bin/eolian_js/eolian/js/format.hh [new file with mode: 0644]
src/bin/eolian_js/main.cc [new file with mode: 0644]
src/bindings/eina_cxx/Eina.hh
src/bindings/eina_cxx/eina_accessor.hh
src/bindings/eina_cxx/eina_array.hh
src/bindings/eina_cxx/eina_clone_allocators.hh
src/bindings/eina_cxx/eina_function.hh [new file with mode: 0644]
src/bindings/eina_cxx/eina_integer_sequence.hh
src/bindings/eina_cxx/eina_list.hh
src/bindings/eina_cxx/eina_logical.hh [new file with mode: 0644]
src/bindings/eina_cxx/eina_pp.hh [new file with mode: 0644]
src/bindings/eina_cxx/eina_ptrarray.hh
src/bindings/eina_cxx/eina_ptrlist.hh
src/bindings/eina_cxx/eina_range_types.hh
src/bindings/eina_cxx/eina_tuple.hh
src/bindings/eina_cxx/eina_tuple_c.hh [new file with mode: 0644]
src/bindings/eina_cxx/eina_type_traits.hh
src/bindings/eldbus_cxx/eldbus_freedesktop.hh
src/bindings/eo_cxx/eo_concrete.hh
src/bindings/js/ecore_js/Ecore_Js.hh [new file with mode: 0644]
src/bindings/js/ecore_js/ecore_js_animator.cc [new file with mode: 0644]
src/bindings/js/ecore_js/ecore_js_event.cc [new file with mode: 0644]
src/bindings/js/ecore_js/ecore_js_idle.cc [new file with mode: 0644]
src/bindings/js/ecore_js/ecore_js_init.cc [new file with mode: 0644]
src/bindings/js/ecore_js/ecore_js_job.cc [new file with mode: 0644]
src/bindings/js/ecore_js/ecore_js_mainloop.cc [new file with mode: 0644]
src/bindings/js/ecore_js/ecore_js_poller.cc [new file with mode: 0644]
src/bindings/js/ecore_js/ecore_js_throttle.cc [new file with mode: 0644]
src/bindings/js/ecore_js/ecore_js_timer.cc [new file with mode: 0644]
src/bindings/js/ecore_js/ecore_js_timer.hh [new file with mode: 0644]
src/bindings/js/efl_js/Efl_Js.hh [new file with mode: 0644]
src/bindings/js/efl_js/efl_js.cc [new file with mode: 0644]
src/bindings/js/eina_js/Eina_Js.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_accessor.cc [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_accessor.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_array.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_compatibility.cc [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_compatibility.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_container.cc [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_container.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_error.cc [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_error.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_get_value.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_get_value_from_c.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_iterator.cc [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_iterator.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_list.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_log.cc [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_log.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_node.hh [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_value.cc [new file with mode: 0644]
src/bindings/js/eina_js/eina_js_value.hh [new file with mode: 0644]
src/bindings/js/eio_js/Eio_Js.hh [new file with mode: 0644]
src/bindings/js/eio_js/eio_js.cc [new file with mode: 0644]
src/bindings/js/eldbus_js/Eldbus_Js.hh [new file with mode: 0644]
src/bindings/js/eldbus_js/eldbus_js_connection.cc [new file with mode: 0644]
src/bindings/js/eldbus_js/eldbus_js_core.cc [new file with mode: 0644]
src/bindings/js/eldbus_js/eldbus_js_message.cc [new file with mode: 0644]
src/bindings/js/eldbus_js/eldbus_js_object_mapper.cc [new file with mode: 0644]
src/bindings/js/eldbus_js/eldbus_js_util.hh [new file with mode: 0644]
src/bindings/js/eo_js/Eo_Js.hh [new file with mode: 0644]
src/bindings/js/eo_js/eo_js_call_function.hh [new file with mode: 0644]
src/bindings/js/eo_js/eo_js_construct_from_eo.hh [new file with mode: 0644]
src/bindings/js/eo_js/eo_js_constructor.hh [new file with mode: 0644]
src/bindings/js/eo_js/eo_js_direction.hh [new file with mode: 0644]
src/bindings/js/eo_js/eo_js_event.hh [new file with mode: 0644]
src/bindings/js/eo_js/eo_js_namespace.hh [new file with mode: 0644]
src/bindings/js/eo_js/eo_js_struct.hh [new file with mode: 0644]
src/bindings/js/ethumb_js/Ethumb_Js.hh [new file with mode: 0644]
src/bindings/js/ethumb_js/ethumb_js_client.cc [new file with mode: 0644]
src/lib/ecore/ecore.c
src/lib/ecore/ecore_main.c
src/lib/ecore/ecore_private.h
src/lib/ecore_con/Ecore_Con_Eet.h
src/lib/efl/interfaces/efl_model_base.eo
src/lib/emotion/Emotion.h
src/lib/emotion/emotion_smart.c
src/lib/eo/Eo.h
src/tests/.gitignore
src/tests/ecore/ecore_test_ecore.c
src/tests/ecore/ecore_test_ecore_x.c
src/tests/efl_js/benchmark_js_suite.cc [new file with mode: 0644]
src/tests/efl_js/benchmark_js_suite.js [new file with mode: 0755]
src/tests/efl_js/benchmark_object.eo [new file with mode: 0644]
src/tests/efl_js/benchmark_object_impl.cc [new file with mode: 0644]
src/tests/efl_js/ecore_js_suite.cc [new file with mode: 0644]
src/tests/efl_js/ecore_js_suite.js [new file with mode: 0755]
src/tests/efl_js/eina_js_containers_suite.cc [new file with mode: 0644]
src/tests/efl_js/eina_js_containers_suite.js [new file with mode: 0755]
src/tests/efl_js/eina_js_suite.cc [new file with mode: 0644]
src/tests/efl_js/eina_js_suite.js [new file with mode: 0755]
src/tests/efl_js/eio_js_suite.cc [new file with mode: 0644]
src/tests/efl_js/eio_js_suite.js [new file with mode: 0755]
src/tests/efl_js/eldbus_js_suite.cc [new file with mode: 0644]
src/tests/efl_js/eldbus_js_suite.js [new file with mode: 0755]
src/tests/efl_js/ethumb_js_suite.cc [new file with mode: 0644]
src/tests/efl_js/ethumb_js_suite.js [new file with mode: 0755]
src/tests/efl_js/suite_runner.hh [new file with mode: 0644]
src/tests/efl_js/testproj/hello.project [new file with mode: 0644]
src/tests/efl_js/testproj/hello.txt [new file with mode: 0644]
src/tests/efl_js/testproj/main.js [new file with mode: 0644]
src/tests/efl_js/timer.js [new file with mode: 0644]
src/tests/eolian_js/constructor_method_class.eo [new file with mode: 0644]
src/tests/eolian_js/eolian_js_suite.cc [new file with mode: 0644]
src/tests/eolian_js/eolian_js_suite.js [new file with mode: 0755]
src/tests/eolian_js/eolian_js_test_constructor_method_impl.c [new file with mode: 0644]
src/tests/eolian_js/eolian_js_test_eolian_js_binding.cc [new file with mode: 0644]
src/tests/eolian_js/eolian_js_test_evas_box.cc [new file with mode: 0644]
src/tests/eolian_js/eolian_js_test_test_object_impl.c [new file with mode: 0644]
src/tests/eolian_js/test_object.eo [new file with mode: 0644]

index d93f853..c779341 100644 (file)
@@ -35,6 +35,7 @@ tags
 *.eo.legacy.h
 *.eo.hh
 *.eo.impl.hh
+*.eo.js.cc
 *.eo.lua
 *.luac
 .dir-locals.el
index 8363720..2e90bf3 100644 (file)
@@ -172,6 +172,14 @@ if HAVE_ELUA
 pkgconfig_DATA += pc/elua.pc
 endif
 
+if HAVE_JS
+pkgconfig_DATA += \
+pc/eolian-js.pc \
+pc/efl-js.pc \
+pc/eo-js.pc \
+pc/eina-js.pc
+endif
+
 if BUILD_ENGINE_SOFTWARE_X11
 pkgconfig_DATA += pc/evas-software-x11.pc
 endif
index 08976a5..6e5953b 100644 (file)
@@ -1051,6 +1051,191 @@ EFL_EVAL_PKGS([EINA_CXX])
 EFL_LIB_END([Eina_Cxx])
 #### End of Eina CXX
 
+AC_ARG_WITH([js],
+   [AS_HELP_STRING([--with-js=@<:@nodejs/libv8/libuv/none@:>@],[enable JavaScript bindings using nodejs or libv8/libuv as build dependencies. The libuv option implies libv8. @<:@default=none@:>@])],
+   [want_js="${withval}"], [want_js="none"])
+
+EFLJS_CXXFLAGS=""
+AC_LANG_PUSH([C++])
+case "$want_js" in
+     nodejs)
+        AC_CHECK_HEADERS([node/v8.h nodejs/deps/v8/v8.h nodejs/deps/v8/include/v8.h nodejs/src/v8.h v8.h],
+                         [
+                           v8_header=AC_header
+                           v8_header_define=AS_TR_CPP([HAVE_]AC_header)
+                           EFLJS_CXXFLAGS="$EFLJS_CXXFLAGS -D$v8_header_define"
+                           break
+                         ]
+                         [AC_MSG_ERROR([Could not find v8 include headers from nodejs.])])
+        AC_CHECK_HEADERS([node/node.h nodejs/deps/node/node.h nodejs/deps/node/include/node.h nodejs/src/node.h node.h],
+                         [
+                           node_header_define=AS_TR_CPP([HAVE_]AC_header)
+                           EFLJS_CXXFLAGS="$EFLJS_CXXFLAGS -D$node_header_define"
+                           break
+                         ]
+                         [AC_MSG_ERROR([Could not find node include headers from nodejs.])])
+        AC_CHECK_HEADERS([node/uv.h nodejs/deps/uv/uv.h nodejs/deps/uv/include/uv.h nodejs/src/uv.h uv.h],
+                         [
+                           uv_header_define=AS_TR_CPP([HAVE_]AC_header)
+                           EFLJS_CXXFLAGS="$EFLJS_CXXFLAGS -D$uv_header_define"
+                           break
+                         ]
+                         [AC_MSG_ERROR([Could not find uv include headers from nodejs.])])
+        ;;
+     libv8)
+        AC_CHECK_HEADERS([v8.h],
+                         [
+                           v8_header=AC_header
+                           break
+                         ]
+                         [AC_MSG_ERROR([Could not find v8 include headers from libv8.])])
+        ;;
+     libuv)
+        AC_CHECK_HEADERS([v8.h],
+                         [
+                           v8_header=AC_header
+                           break
+                         ]
+                         [AC_MSG_ERROR([Could not find v8 include headers from libv8.])])
+        AC_CHECK_HEADERS([uv.h],
+                         [break]
+                         [AC_MSG_ERROR([Could not find uv include headers from libuv.])])
+        ;;
+     none)
+        ;;
+     *) AC_MSG_ERROR([Invalid javascript dependency (${want_js}): must be none, nodejs, libv8 or libuv]) ;;
+esac
+
+have_v8_global="no"
+have_v8_create_params="no"
+if test "$want_js" != "none" ; then
+AC_COMPILE_IFELSE(
+   [AC_LANG_PROGRAM(
+       [[
+#include "$v8_header"
+       ]],
+       [[
+v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = nullptr;
+       ]])
+   ],
+   [
+    AC_DEFINE(HAVE_V8_CREATE_PARAMS, 1, [Define to 1 if you must pass create_params explicitly.])
+    have_v8_create_params="yes"
+    AC_MSG_NOTICE([checking for v8::Isolate::CreateParams... yes])
+   ],
+   [
+    AC_MSG_NOTICE([checking for v8::Isolate::CreateParams... no])
+   ])
+AC_COMPILE_IFELSE(
+   [AC_LANG_PROGRAM(
+       [[
+#include "$v8_header"
+#include <type_traits>
+       ]],
+       [[
+       static_assert((std::is_same< ::v8::Global<void>, ::v8::UniquePersistent<void>>::value), "");
+       ]])
+   ],
+   [
+    AC_DEFINE(HAVE_V8_GLOBAL, 1, [Define to 1 if you must pass create_params explicitly.])
+    have_v8_global="yes"
+    AC_MSG_NOTICE([checking for v8::Global<T> class... yes])
+   ],
+   [
+    AC_MSG_NOTICE([checking for v8::Global<T> class... no])
+   ])
+fi
+AM_CONDITIONAL([HAVE_V8_CREATE_PARAMS], [test "x${have_v8_create_params}" = "xyes"])
+AM_CONDITIONAL([HAVE_V8_GLOBAL], [test "x${have_v8_global}" = "xyes"])
+AC_SUBST([HAVE_V8_CREATE_PARAMS])
+AC_SUBST([HAVE_V8_GLOBAL])
+AC_LANG_POP([C++])
+
+AM_CONDITIONAL([HAVE_NODEJS], [test "x${want_js}" = "xnodejs"])
+AC_DEFINE_IF([HAVE_NODEJS], [test "x${want_js}" = "xnodejs"],
+  [1], [Using NodeJS])
+AC_SUBST([want_js])
+AC_SUBST([HAVE_NODEJS])
+
+have_js="no"
+if test "x${want_js}" != "xnone" ; then
+   have_js="yes"
+fi
+AM_CONDITIONAL([HAVE_JS], [test "x${have_js}" = "xyes"])
+AC_DEFINE_IF([HAVE_JS], [test "x${have_js}" = "xyes"], [1], [Compiling bindings for JavaScript])
+AC_SUBST([HAVE_JS])
+
+AM_CONDITIONAL([HAVE_LIBUV], [test "x${want_js}" = "xnodejs" -o "x${want_js}" = "xlibuv"])
+AC_DEFINE_IF([HAVE_LIBUV], [test "x${want_js}" = "xnodejs" -o "x${want_js}" = "xlibuv"],
+             [1], [Compiling libuv event loop integration])
+AC_SUBST([HAVE_LIBUV])
+
+# For efljspack mime handling
+AM_CONDITIONAL([HAVE_XDG_DATA_HOME], [test "x${XDG_DATA_HOME}" != "x"])
+AM_COND_IF([HAVE_XDG_DATA_HOME], [AC_SUBST([XDG_DATA_HOME])], [AC_SUBST([XDG_DATA_HOME], "$HOME/.local/share")])
+
+#### Eina JS
+EFL_LIB_START_OPTIONAL([Eina_Js], [test "x${have_js}" = "xyes"])
+EFL_INTERNAL_DEPEND_PKG([EINA_JS], [Eina])
+EFL_INTERNAL_DEPEND_PKG([EINA_JS], [Eo])
+EFL_ADD_CFLAGS([EINA_JS], [${EFL_PTHREAD_CFLAGS}])
+EFL_EVAL_PKGS([EINA_JS])
+
+EFL_LIB_END_OPTIONAL([Eina_Js])
+#### End of Eina JS
+
+#### Ecore JS
+EFL_LIB_START_OPTIONAL([Ecore_Js], [test "x${have_js}" = "xyes"])
+
+EFL_INTERNAL_DEPEND_PKG([ECORE_JS], [ecore])
+EFL_INTERNAL_DEPEND_PKG([ECORE_JS], [ecore_file])
+EFL_ADD_CFLAGS([ECORE_JS], [${EFL_PTHREAD_CFLAGS}])
+EFL_EVAL_PKGS([ECORE_JS])
+
+EFL_LIB_END_OPTIONAL([Ecore_Js])
+#### End of Ecore JS
+
+#### Eio JS
+EFL_LIB_START_OPTIONAL([Eio_Js], [test "x${have_js}" = "xyes"])
+
+EFL_INTERNAL_DEPEND_PKG([EIO_JS], [eio])
+EFL_ADD_CFLAGS([EIO_JS], [${EFL_PTHREAD_CFLAGS}])
+EFL_EVAL_PKGS([EIO_JS])
+
+EFL_LIB_END_OPTIONAL([Eio_Js])
+#### End of Eio JS
+
+#### Ethumb JS
+EFL_LIB_START_OPTIONAL([Ethumb_Js], [test "x${have_js}" = "xyes"])
+
+EFL_INTERNAL_DEPEND_PKG([ETHUMB_JS], [ethumb])
+EFL_INTERNAL_DEPEND_PKG([ETHUMB_JS], [ethumb_client])
+EFL_ADD_CFLAGS([ETHUMB_JS], [${EFL_PTHREAD_CFLAGS}])
+EFL_EVAL_PKGS([ETHUMB_JS])
+
+EFL_LIB_END_OPTIONAL([Ethumb_Js])
+#### End of Ethumb JS
+
+#### Eldbus JS
+EFL_LIB_START_OPTIONAL([Eldbus_Js], [test "x${have_js}" = "xyes"])
+
+EFL_INTERNAL_DEPEND_PKG([ELDBUS_JS], [eldbus])
+EFL_ADD_CFLAGS([ELDBUS_JS], [${EFL_PTHREAD_CFLAGS}])
+EFL_EVAL_PKGS([ELDBUS_JS])
+
+EFL_LIB_END_OPTIONAL([Eldbus_Js])
+#### End of Eldbus JS
+
+#### Eo JS
+EFL_LIB_START_OPTIONAL([Eo_Js], [test "x${have_js}" = "xyes"])
+
+EFL_INTERNAL_DEPEND_PKG([EO_JS], [eina])
+EFL_ADD_CFLAGS([EO_JS], [${EFL_PTHREAD_CFLAGS}])
+EFL_EVAL_PKGS([EO_JS])
+
+EFL_LIB_END_OPTIONAL([Eo_Js])
+#### End of Eo JS
+
 #### Eo
 
 EFL_LIB_START([Eo])
@@ -1244,6 +1429,15 @@ EFL_INTERNAL_DEPEND_PKG([EOLIAN], [eina])
 EFL_LIB_END([Eolian])
 #### End of Eolian
 
+EFL_LIB_START_OPTIONAL([Eolian_Js], [test "${have_js}" = "yes"])
+
+EFL_INTERNAL_DEPEND_PKG([EOLIAN_JS], [eina])
+EFL_INTERNAL_DEPEND_PKG([EOLIAN_JS], [eolian])
+
+EFL_LIB_END_OPTIONAL([Eolian_Js])
+#### End of Eolian
+
+
 EFL_LIB_START([Eolian_Cxx])
 ### Default values
 
@@ -2322,6 +2516,17 @@ AC_ARG_ENABLE([g-main-loop],
     fi
    ],
    [want_g_main_loop="no"])
+AC_ARG_ENABLE([libuv],
+   [AS_HELP_STRING([--enable-libuv],[enable ecore_main_loop based on libuv. @<:@default=disabled@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       want_libuv="yes"
+       CFOPT_WARNING="xyes"
+    else
+       want_libuv="no"
+    fi
+   ],
+   [want_libuv="no"])
 
 AC_ARG_ENABLE([gstreamer],
    [AS_HELP_STRING([--enable-gstreamer],[enable gstreamer 0.10 support. @<:@default=disabled@:>@])],
@@ -2410,6 +2615,7 @@ EFL_OPTIONAL_DEPEND_PKG([ECORE], [${want_systemd}], [SYSTEMD], [libsystemd])
 EFL_ADD_FEATURE([ECORE], [systemd-daemon], [${want_systemd}])
 EFL_ADD_FEATURE([ECORE], [glib])
 EFL_ADD_FEATURE([ECORE], [g-main-loop])
+EFL_ADD_FEATURE([ECORE], [libuv])
 
 want_glib_integration_always=no
 if test "x${with_glib}" = "xalways" ; then
@@ -2419,6 +2625,9 @@ fi
 
 if test "x${want_g_main_loop}" = "xyes" ; then
   AC_DEFINE([USE_G_MAIN_LOOP], [1], [Use g_main_loop in ecore])
+  if test "x${want_js}" = "xnodejs" -o "x${want_js}" = "xlibuv" ; then
+    AC_MSG_ERROR([Can't define glib and libuv integration together])
+  fi
 fi
 
 # not EFL_OPTIONAL_DEPEND_PKG() because it's only used for ecore examples
@@ -4007,7 +4216,7 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [emile])
 ECORE_EVAS_MODULE([extn], [${want_ecore_evas_extn}])
 ECORE_EVAS_MODULE([ews], [yes])
 ECORE_EVAS_MODULE([fb], [${want_fb}])
-ECORE_EVAS_MODULE([drm], [${want_drm}], 
+ECORE_EVAS_MODULE([drm], [${want_drm}],
   [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm])])
 ECORE_EVAS_MODULE([gl-drm], [${want_gl_drm}],
   [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_gl_drm}], [ecore-drm])])
@@ -4677,6 +4886,63 @@ EFL_ADD_LIBS([ELOCATION], [-lm])
 EFL_LIB_END([Elocation])
 #### End of Elocation
 
+
+
+#### Efl_Js
+EFL_LIB_START_OPTIONAL([Efl_Js], [test "x${have_js}" = "xyes"])
+
+### Default values
+
+### Additional options to configure
+
+### Checks for programs
+
+### Checks for libraries
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Eina])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Eo])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Ecore])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Eet])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Ecore_Evas])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Ecore_Con])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Ecore_Audio])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Efl])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Evas])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Edje])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Emotion])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Eldbus])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Emile])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Ethumb_Client])
+EFL_INTERNAL_DEPEND_PKG([EFL_JS], [Eio])
+
+AM_COND_IF([HAVE_NODEJS], [], [ EFL_ADD_LIBS([EFL_JS], [-lv8]) ])
+
+EFL_EVAL_PKGS([EFL_JS])
+
+AM_COND_IF([HAVE_NODEJS], [EFLJS_CXXFLAGS="$EFLJS_CXXFLAGS -DHAVE_NODEJS"], [])
+AM_COND_IF([HAVE_LIBUV], [EFLJS_CXXFLAGS="$EFLJS_CXXFLAGS -DHAVE_LIBUV"], [])
+AM_COND_IF([HAVE_JS], [EFLJS_CXXFLAGS="$EFLJS_CXXFLAGS -DHAVE_JS"], [])
+
+AM_COND_IF([HAVE_V8_CREATE_PARAMS], [EFLJS_CXXFLAGS="$EFLJS_CXXFLAGS -DHAVE_V8_CREATE_PARAMS"], [])
+AM_COND_IF([HAVE_V8_GLOBAL], [EFLJS_CXXFLAGS="$EFLJS_CXXFLAGS -DHAVE_V8_GLOBAL"], [])
+AC_SUBST([EFLJS_CXXFLAGS])
+
+### Checks for header files
+
+### Checks for types
+
+### Checks for structures
+
+### Checks for compiler characteristics
+
+### Checks for linker characteristics
+
+### Checks for library functions
+
+### Check availability
+
+EFL_LIB_END_OPTIONAL([Efl_Js])
+#### End of Efl_Js
+
 ### Add Wayland server library if test is enabled
 if test "x${want_tests}" = "xyes" -a "x${want_wayland}" = "xyes"; then
    EFL_DEPEND_PKG([ECORE_WAYLAND_SRV], [WAYLAND], [wayland-server >= 1.8.0])
@@ -4809,6 +5075,10 @@ pc/eo.pc
 pc/eo-cxx.pc
 pc/eolian.pc
 pc/eolian-cxx.pc
+pc/eina-js.pc
+pc/efl-js.pc
+pc/eolian-js.pc
+pc/eo-js.pc
 pc/efl.pc
 pc/efl-cxx.pc
 pc/evas-fb.pc
@@ -4991,6 +5261,8 @@ echo "  Cryptography..: ${build_crypto}"
 echo "  X11...........: ${with_x11}"
 echo "  OpenGL........: ${with_opengl}"
 echo "  C++11.........: ${have_cxx11}"
+echo "  JavaScript....: ${want_js}"
+echo "  JavaScript flg: $EINA_JS_LIBS"
 echo "Eina............: yes (${features_eina} unwind=$have_unwind)"
 echo "Eo..............: yes (${features_eo})"
 echo "Eolian..........: yes (${features_eolian})"
@@ -5052,6 +5324,7 @@ echo "  CPPFLAGS......: $CPPFLAGS"
 echo "  CFLAGS........: $CFLAGS"
 echo "  CXXFLAGS......: $CXXFLAGS"
 echo "  LDFLAGS.......: $LDFLAGS"
+echo "  EFLJS_CXXFLAGS: $EFLJS_CXXFLAGS"
 
 if test "x${with_binary_edje_cc}" != "x"; then
 echo "  edje_cc.......: ${with_binary_edje_cc}"
index c6b8eb4..1858516 100644 (file)
@@ -28,6 +28,7 @@
 /efreet.pc
 /eina.pc
 /eina-cxx.pc
+/eina-js.pc
 /eet-cxx.pc
 /eio.pc
 /eio-cxx.pc
@@ -36,6 +37,7 @@
 /embryo.pc
 /emotion.pc
 /eo.pc
+/eo-js.pc
 /ephysics.pc
 /escape.pc
 /ethumb.pc
@@ -57,6 +59,7 @@
 /evil.pc
 /eolian.pc
 /eolian-cxx.pc
+/eolian-js.pc
 /eo-cxx.pc
 /evas-cxx.pc
 /ecore-cxx.pc
diff --git a/pc/efl-js.pc.in b/pc/efl-js.pc.in
new file mode 100644 (file)
index 0000000..0c1e00c
--- /dev/null
@@ -0,0 +1,15 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+want_js=@want_js@
+
+Name: EFL JavaScript
+Description: JavaScript C++ helpers for data structures
+Version: @PACKAGE_VERSION@
+Requires.private: @requirements_pc_eina@
+Libs.private: @requirements_libs_eina@
+Libs: -L${libdir} -lefl_js
+Cflags: -I${includedir}/efl-js-@VMAJ@ @EFLJS_CXXFLAGS@
diff --git a/pc/eina-js.pc.in b/pc/eina-js.pc.in
new file mode 100644 (file)
index 0000000..6aab608
--- /dev/null
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+want_js=@want_js@
+
+Name: Eina JavaScript
+Description: JavaScript C++ helpers for data structures
+Version: @PACKAGE_VERSION@
+Requires.private: @requirements_pc_eina@
+Libs.private: @requirements_libs_eina@
+Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/eina-@VMAJ@ -I${includedir}/eina-js-@VMAJ@
\ No newline at end of file
diff --git a/pc/eo-js.pc.in b/pc/eo-js.pc.in
new file mode 100644 (file)
index 0000000..3dedf5c
--- /dev/null
@@ -0,0 +1,15 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+eoincludedir=@datadir@/eolian/include
+eolian_flags=-I${eoincludedir}/eo-@VMAJ@
+
+Name: Eo JavaScript
+Description: JavaScript C++ helpers for bindings for EFL's generic object system.
+Version: @PACKAGE_VERSION@
+Requires.private: @requirements_pc_eo@
+Libs.private: @requirements_libs_eo@
+Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/eo-@VMAJ@ -I${includedir}/eo-js-@VMAJ@
\ No newline at end of file
diff --git a/pc/eolian-js.pc.in b/pc/eolian-js.pc.in
new file mode 100644 (file)
index 0000000..2dbc1ca
--- /dev/null
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+
+Name: Eolian-JS
+Description: EFL's JavaScript bindings generator.
+Version: @VERSION@
+Require.private: @requirements_pc_eolian@
+Libs: -L${libdir} 
+Libs.private: @requirements_libs_eolian@ 
+Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/eolian-js-@VMAJ@ 
index 4fd66b9..c49c058 100644 (file)
@@ -13,4 +13,4 @@ Requires.private: @requirements_pc_evas@
 Version: @VERSION@
 Libs: -L${libdir} -levas
 Libs.private: @requirements_libs_evas@
-Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/evas-@VMAJ@
+Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/evas-@VMAJ@ -I${includedir}/evas-@VMAJ@/canvas
index 6ac8dc7..248711b 100644 (file)
@@ -15,6 +15,7 @@ check_PROGRAMS =
 TESTS =
 EXTRA_DIST =
 
+GENERATED_JS_BINDINGS =
 
 EFL_INSTALL_EXEC_HOOK=
 
@@ -76,6 +77,21 @@ include Makefile_Eio_Cxx.am
 include Makefile_Elua.am
 include Makefile_Elocation.am
 
+if HAVE_JS
+AM_V_CP = $(am__v_CP_@AM_V@)
+am__v_CP_ = $(am__v_CP_@AM_DEFAULT_V@)
+am__v_CP_0 = @echo "  CP  " $@;
+CP = cp
+if EFL_ENABLE_TESTS
+if HAVE_NODEJS
+AM_TESTS_ENVIRONMENT = NODE_PATH='$(abs_builddir)/lib/efl_js:$(abs_builddir)/tests/eolian_js:$(abs_builddir)/tests/efl_js'; export NODE_PATH;
+endif
+endif
+endif
+
+include Makefile_Eolian_Js.am
+include Makefile_Efl_Js.am
+
 .PHONY: benchmark examples
 
 BENCHMARK_SUBDIRS = \
index b7e0b6b..13e5473 100644 (file)
@@ -271,3 +271,13 @@ installed_ecoreluadir = $(datadir)/elua/modules/ecore
 nodist_installed_ecorelua_DATA = $(generated_ecore_lua_all)
 
 endif
+
+if HAVE_JS
+
+generated_ecore_js_bindings = $(ecore_eolian_files:%.eo=%.eo.js.cc)
+
+CLEANFILES += $(generated_ecore_js_bindings)
+
+GENERATED_JS_BINDINGS += $(generated_ecore_js_bindings)
+
+endif
index ccce8f7..b500118 100644 (file)
@@ -104,4 +104,15 @@ nodist_installed_ecoreaudiolua_DATA = $(generated_ecore_audio_lua_all)
 
 endif
 
+if HAVE_JS
+
+generated_ecore_audio_js_bindings = $(ecore_audio_eolian_files:%.eo=%.eo.js.cc)
+
+CLEANFILES += $(generated_ecore_audio_js_bindings)
+
+GENERATED_JS_BINDINGS += $(generated_ecore_audio_js_bindings)
+
 endif
+
+endif
+
index 87ad889..544e6d9 100644 (file)
@@ -143,3 +143,13 @@ installed_ecoreconluadir = $(datadir)/elua/modules/ecore_con
 nodist_installed_ecoreconlua_DATA = $(generated_ecore_con_lua_all)
 
 endif
+
+if HAVE_JS
+
+generated_ecore_con_js_bindings = $(ecore_con_eolian_files:%.eo=%.eo.js.cc)
+
+CLEANFILES += $(generated_ecore_con_js_bindings)
+
+GENERATED_JS_BINDINGS += $(generated_ecore_con_js_bindings)
+
+endif
diff --git a/src/Makefile_Ecore_Js.am b/src/Makefile_Ecore_Js.am
new file mode 100644 (file)
index 0000000..df5ac2f
--- /dev/null
@@ -0,0 +1,19 @@
+
+### Library
+
+if HAVE_JS
+installed_ecorejsheadersdir = $(includedir)/ecore-js-@VMAJ@
+dist_installed_ecorejsheaders_DATA = \
+bindings/js/ecore_js/Ecore_Js.hh \
+bindings/js/ecore_js/ecore_js_init.hh \
+bindings/js/ecore_js/ecore_js_mainloop.hh \
+bindings/js/ecore_js/ecore_js_timer.hh \
+bindings/js/ecore_js/ecore_js_event.hh \
+bindings/js/ecore_js/ecore_js_job.hh \
+bindings/js/ecore_js/ecore_js_idle.hh \
+bindings/js/ecore_js/ecore_js_animator.hh \
+bindings/js/ecore_js/ecore_js_poller.hh \
+bindings/js/ecore_js/ecore_js_throttle.hh \
+bindings/js/ecore_js/ecore_js_file.hh
+endif
+
index ca0eefc..4fa0ecf 100644 (file)
@@ -130,7 +130,7 @@ if HAVE_WIN32
 USE_EDJE_BIN_LIBS = -L$(top_builddir)/src/lib/evil @USE_EDJE_LIBS@
 else
 USE_EDJE_BIN_LIBS = @USE_EDJE_LIBS@
-endif         
+endif
 
 bin_PROGRAMS += \
 bin/edje/edje_cc \
@@ -334,3 +334,13 @@ installed_edjeluadir = $(datadir)/elua/modules/edje
 nodist_installed_edjelua_DATA = $(generated_edje_lua_all)
 
 endif
+
+if HAVE_JS
+
+generated_edje_js_bindings = $(edje_eolian_files:%.eo=%.eo.js.cc)
+
+CLEANFILES += $(generated_edje_js_bindings)
+
+GENERATED_JS_BINDINGS += $(generated_edje_js_bindings)
+
+endif
index f6b1c28..9e59bf2 100644 (file)
@@ -80,6 +80,16 @@ nodist_installed_efllua_DATA = $(generated_efl_lua_all)
 
 endif
 
+if HAVE_JS
+
+generated_efl_js_bindings = $(efl_eolian_files:%.eo=%.eo.js.cc)
+
+CLEANFILES += $(generated_efl_js_bindings)
+
+GENERATED_JS_BINDINGS += $(generated_efl_js_bindings)
+
+endif
+
 ### Binary
 
 bin_PROGRAMS += \
diff --git a/src/Makefile_Efl_Js.am b/src/Makefile_Efl_Js.am
new file mode 100644 (file)
index 0000000..e993120
--- /dev/null
@@ -0,0 +1,333 @@
+if HAVE_JS
+
+if HAVE_NODEJS
+
+noinst_lib_LTLIBRARIES = lib/efl_js/libefl_node_js.la
+noinst_libdir = $(libdir)/efl_js
+
+$(top_builddir)/src/lib/efl_js/efl.node: lib/efl_js/libefl_node_js.la
+       $(AM_V_CP)$(CP) $(top_builddir)/src/lib/efl_js/.libs/libefl_node_js.so $(top_builddir)/src/lib/efl_js/efl.node
+
+eflnodedir = $(libdir)/node_modules
+eflnode_DATA = $(top_builddir)/src/lib/efl_js/efl.node
+
+CLEANFILES += ${eflnodedir_DATA}
+EXTRA_DIST += ${eflnodedir_DATA}
+
+efljsmimedir = @XDG_DATA_HOME@/mime/packages
+efljsmime_DATA = bin/efl_js/efljslaunch.xml
+
+efljsdesktopdir = @XDG_DATA_HOME@/applications
+efljsdesktop_DATA = bin/efl_js/efljslaunch.desktop
+
+bin_SCRIPTS += \
+       bin/efl_js/efljslaunch \
+       bin/efl_js/efljspack
+
+else
+
+bin_PROGRAMS += bin/efl_js/eflv8js
+
+bin_efl_js_eflv8js_SOURCES = \
+       bin/efl_js/launcher_main.cc
+
+bin_efl_js_eflv8js_CPPFLAGS = \
+       -I$(top_builddir)/src/lib/efl \
+       -I$(top_srcdir)/src/bindings/js/efl_js \
+        -I$(top_srcdir)/src/bindings/js/eina_js \
+        -I$(top_srcdir)/src/bindings/js/eo_js \
+       @CHECK_CFLAGS@ \
+       @EINA_CXX_CFLAGS@ \
+       @EO_CXX_CFLAGS@ \
+       @EMILE_CFLAGS@ \
+       @ECORE_CFLAGS@ \
+       @EET_CFLAGS@ \
+       @EO_CFLAGS@ \
+       @EFL_JS_CFLAGS@ \
+       @EINA_JS_CFLAGS@ \
+       @EO_JS_CFLAGS@
+
+bin_efl_js_eflv8js_LDFLAGS = \
+       -lv8 \
+       @USE_EFL_JS_INTERNAL_LIBS@
+
+bin_efl_js_eflv8js_LDADD = \
+       @USE_EFL_JS_LIBS@
+
+endif
+
+bindings/js/efl_js/eolian_js_bindings.cc: $(GENERATED_JS_BINDINGS)
+       @echo @ECHO_E@ "#ifdef HAVE_CONFIG_H" > $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include \"config.h\"" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#endif\n" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include <Efl.h>" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include <Efl_Config.h>" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include <Ecore.h>" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include <Eo.h>" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include <Ecore_Con.h>" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include <Ecore_Audio.h>" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include <Evas.h>" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include <Edje.h>" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include <Ecore_Con_Eet.h>" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @echo @ECHO_E@ "#include <Emotion.h>\n" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc
+       @for i in $(GENERATED_JS_BINDINGS); do echo "#include <$$i>" >> $(top_builddir)/src/bindings/js/efl_js/eolian_js_bindings.cc; done
+
+CLEANFILES += bindings/js/efl_js/eolian_js_bindings.cc
+
+## Install Ecore-JS headers
+installed_ecorejsheadersdir = $(includedir)/ecore-js-@VMAJ@
+dist_installed_ecorejsheaders_DATA = \
+bindings/js/ecore_js/Ecore_Js.hh
+
+## Install Eio-JS headers
+installed_eiojsheadersdir = $(includedir)/eio-js-@VMAJ@
+dist_installed_eiojsheaders_DATA = \
+bindings/js/eio_js/Eio_Js.hh
+
+## Install Ethumb-JS headers
+installed_ethumbjsheadersdir = $(includedir)/ethumb-js-@VMAJ@
+dist_installed_ethumbjsheaders_DATA = \
+bindings/js/ethumb_js/Ethumb_Js.hh
+
+## Install Eldbus-JS headers
+installed_eldbusjsheadersdir = $(includedir)/eldbus-js-@VMAJ@
+dist_installed_eldbusjsheaders_DATA = \
+bindings/js/eldbus_js/Eldbus_Js.hh
+
+## Install Eo-JS headers
+installed_eojsmainheadersdir = $(includedir)/eo-js-@VMAJ@
+dist_installed_eojsmainheaders_DATA = \
+bindings/js/eo_js/eo_js_call_function.hh \
+bindings/js/eo_js/eo_js_constructor.hh \
+bindings/js/eo_js/eo_js_direction.hh \
+bindings/js/eo_js/eo_js_event.hh \
+bindings/js/eo_js/eo_js_namespace.hh \
+bindings/js/eo_js/eo_js_struct.hh \
+bindings/js/eo_js/eo_js_construct_from_eo.hh \
+bindings/js/eo_js/Eo_Js.hh
+
+## Install Eina-JS headers
+installed_einajsheadersdir = $(includedir)/eina-js-@VMAJ@
+dist_installed_einajsheaders_DATA = \
+bindings/js/eina_js/Eina_Js.hh \
+bindings/js/eina_js/eina_js_accessor.hh \
+bindings/js/eina_js/eina_js_array.hh \
+bindings/js/eina_js/eina_js_compatibility.hh \
+bindings/js/eina_js/eina_js_container.hh \
+bindings/js/eina_js/eina_js_error.hh \
+bindings/js/eina_js/eina_js_get_value_from_c.hh \
+bindings/js/eina_js/eina_js_get_value.hh \
+bindings/js/eina_js/eina_js_iterator.hh \
+bindings/js/eina_js/eina_js_list.hh \
+bindings/js/eina_js/eina_js_log.hh \
+bindings/js/eina_js/eina_js_node.hh \
+bindings/js/eina_js/eina_js_value.hh
+
+installed_efljsheadersdir = $(includedir)/efl-js-@VMAJ@
+dist_installed_efljsheaders_DATA = \
+bindings/js/efl_js/Efl_Js.hh
+
+lib_LTLIBRARIES += lib/efl_js/libefl_js.la
+
+lib_efl_js_libefl_js_la_SOURCES = \
+bindings/js/eina_js/eina_js_container.cc \
+bindings/js/eina_js/eina_js_value.cc \
+bindings/js/eina_js/eina_js_error.cc \
+bindings/js/eina_js/eina_js_accessor.cc \
+bindings/js/eina_js/eina_js_log.cc \
+bindings/js/eina_js/eina_js_iterator.cc \
+bindings/js/eina_js/eina_js_compatibility.cc \
+bindings/js/ecore_js/ecore_js_init.cc \
+bindings/js/ecore_js/ecore_js_mainloop.cc \
+bindings/js/ecore_js/ecore_js_timer.cc \
+bindings/js/ecore_js/ecore_js_event.cc \
+bindings/js/ecore_js/ecore_js_job.cc \
+bindings/js/ecore_js/ecore_js_idle.cc \
+bindings/js/ecore_js/ecore_js_animator.cc \
+bindings/js/ecore_js/ecore_js_poller.cc \
+bindings/js/ecore_js/ecore_js_throttle.cc \
+bindings/js/eldbus_js/eldbus_js_core.cc \
+bindings/js/eldbus_js/eldbus_js_connection.cc \
+bindings/js/eldbus_js/eldbus_js_message.cc \
+bindings/js/eldbus_js/eldbus_js_object_mapper.cc \
+bindings/js/eio_js/eio_js.cc \
+bindings/js/ethumb_js/ethumb_js_client.cc
+
+nodist_lib_efl_js_libefl_js_la_SOURCES = \
+bindings/js/efl_js/eolian_js_bindings.cc
+
+bindings/js/efl_js/efl_js.cc $(lib_efl_js_libefl_js_la_SOURCES): $(generated_ecore_cxx_all) $(generated_eo_cxx_bindings) $(generated_efl_cxx_all)
+
+lib_efl_js_libefl_js_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
+-I$(top_srcdir)/src/lib/efl \
+-I$(top_builddir)/src/lib/efl/interfaces/ \
+-I$(top_builddir)/src/lib/evas/canvas/ \
+-I$(top_srcdir)/src/bindings/js/eina_js \
+-I$(top_srcdir)/src/bindings/js/ecore_js \
+-I$(top_srcdir)/src/bindings/js/eo_js \
+-I$(top_srcdir)/src/bindings/js/eldbus_js \
+-I$(top_srcdir)/src/bindings/js/eio_js \
+-I$(top_srcdir)/src/bindings/js/ethumb_js \
+@EFL_JS_CFLAGS@ \
+@EO_JS_CFLAGS@ \
+@ECORE_CXX_CFLAGS@ \
+@EO_CXX_CFLAGS@ \
+@ECORE_JS_CFLAGS@ \
+@EINA_JS_CFLAGS@ \
+@ELDBUS_JS_CFLAGS@ \
+@EIO_JS_CFLAGS@ \
+@ETHUMB_JS_CFLAGS@ \
+@EINA_CXX_CFLAGS@
+lib_efl_js_libefl_js_la_LIBADD = @EFL_JS_LIBS@
+lib_efl_js_libefl_js_la_DEPENDENCIES = @EFL_JS_INTERNAL_LIBS@
+lib_efl_js_libefl_js_la_LIBTOOLFLAGS = --tag=disable-static
+lib_efl_js_libefl_js_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
+
+if HAVE_NODEJS
+lib_efl_js_libefl_node_js_la_SOURCES = \
+bindings/js/efl_js/efl_js.cc
+
+lib_efl_js_libefl_node_js_la_CPPFLAGS = $(lib_efl_js_libefl_js_la_CPPFLAGS)
+lib_efl_js_libefl_node_js_la_LIBADD = @USE_EFL_JS_LIBS@
+lib_efl_js_libefl_node_js_la_DEPENDENCIES = @USE_EFL_JS_INTERNAL_LIBS@
+lib_efl_js_libefl_node_js_la_LIBTOOLFLAGS = --tag=disable-static
+lib_efl_js_libefl_node_js_la_LDFLAGS =
+else
+lib_efl_js_libefl_js_la_SOURCES += \
+bindings/js/efl_js/efl_js.cc
+endif
+
+if EFL_ENABLE_TESTS
+
+SUITE_RUNNER_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
+-I$(top_srcdir)/src/bindings/js/eina_js \
+-I$(top_srcdir)/src/bindings/js/eo_js \
+-DTESTS_WD=\"`pwd`\" \
+-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/efl_js\" \
+-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)/src/tests/efl_js\" \
+-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/efl_js\" \
+@CHECK_CFLAGS@ \
+@EFL_JS_CFLAGS@ \
+@EINA_CXX_CFLAGS@ \
+@EO_CXX_CFLAGS@ \
+@EO_CFLAGS@ \
+@ECORE_CFLAGS@ \
+@ECORE_CXX_CFLAGS@ \
+@ECORE_JS_CFLAGS@ \
+@EINA_JS_CFLAGS@
+
+if HAVE_NODEJS
+TESTS += tests/efl_js/eina_js_suite.js \
+tests/efl_js/eina_js_containers_suite.js \
+tests/efl_js/ecore_js_suite.js \
+tests/efl_js/eldbus_js_suite.js \
+tests/efl_js/ethumb_js_suite.js \
+tests/efl_js/eio_js_suite.js \
+tests/efl_js/benchmark_js_suite.js
+
+check_LTLIBRARIES += tests/efl_js/libbenchmark_object.la
+
+tests/efl_js/eina_js_suite.js tests/efl_js/eina_js_containers_suite.js tests/efl_js/ecore_js_suite.js tests/efl_js/eldbus_js_suite.js tests/efl_js/eio_js_suite.js tests/efl_js/ethumb_js_suite.js: $(top_builddir)/src/lib/efl_js/efl.node
+
+tests/efl_js/benchmark_object.node: tests/efl_js/libbenchmark_object.la
+       $(AM_V_CP)$(CP) $(top_builddir)/src/tests/efl_js/.libs/libbenchmark_object.so $(top_builddir)/src/tests/efl_js/benchmark_object.node
+tests/efl_js/benchmark_js_suite.js: $(top_builddir)/src/lib/efl_js/efl.node tests/efl_js/benchmark_object.node
+
+tests_efl_js_libbenchmark_object_la_SOURCES = tests/efl_js/benchmark_object_impl.cc
+tests_efl_js_libbenchmark_object_la_CPPFLAGS = \
+-I$(top_builddir)/src/lib/efl \
+-I$(top_srcdir)/src/bindings/js/efl_js \
+-I$(top_builddir)/src/tests/efl_js \
+-I$(top_srcdir)/src/bindings/js/eina_js \
+-I$(top_srcdir)/src/bindings/js/eo_js \
+-DTESTS_WD=\"`pwd`\" \
+-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/efl_js\" \
+-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)/src/tests/efl_js\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/efl_js\" \
+-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/efl_js\" \
+@CHECK_CFLAGS@ @EOLIAN_CXX_CFLAGS@ @EINA_JS_CFLAGS@ @EO_JS_CFLAGS@ \
+@EOLIAN_CFLAGS@ @EINA_CFLAGS@ @EO_CFLAGS@ @ECORE_CFLAGS@ @EINA_CXX_CFLAGS@ \
+@EO_JS_CFLAGS@ @EO_CXX_CFLAGS@
+tests_efl_js_libbenchmark_object_la_LIBADD = \
+@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EFL_JS_LIBS@
+tests_efl_js_libbenchmark_object_la_LDFLAGS = -rpath $(abs_top_builddir)/tests/efl_js @EFL_LTLIBRARY_FLAGS@
+tests_efl_js_libbenchmark_object_la_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@
+tests_efl_js_libbenchmark_object_la_LIBTOOLFLAGS = --tag=disable-static
+
+tests/efl_js/tests_efl_js_libbenchmark_object_la-benchmark_object_impl.l$(OBJEXT): tests/efl_js/benchmark_object.eo.js.cc tests/efl_js/benchmark_object.eo.c tests/efl_js/benchmark_object.eo.h
+else
+check_PROGRAMS += \
+tests/efl_js/eina_js_suite \
+tests/efl_js/eina_js_containers_suite \
+tests/efl_js/ecore_js_suite \
+tests/efl_js/eldbus_js_suite \
+tests/efl_js/ethumb_js_suite \
+tests/efl_js/eio_js_suite \
+tests/efl_js/benchmark_js_suite
+TESTS += tests/efl_js/eina_js_suite \
+tests/efl_js/ecore_js_suite \
+tests/efl_js/eldbus_js_suite \
+tests/efl_js/ethumb_js_suite \
+tests/efl_js/eio_js_suite \
+tests/efl_js/benchmark_js_suite
+
+tests_efl_js_eina_js_suite_SOURCES = \
+tests/efl_js/eina_js_suite.cc
+
+tests_efl_js_eina_js_suite_CPPFLAGS = $(SUITE_RUNNER_CPPFLAGS)
+tests_efl_js_eina_js_suite_LDADD = \
+@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EFL_JS_LIBS@
+tests_efl_js_eina_js_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@
+
+tests_efl_js_eina_js_containers_suite_SOURCES = \
+tests/efl_js/eina_js_containers_suite.cc
+
+tests_efl_js_eina_js_containers_suite_CPPFLAGS = $(SUITE_RUNNER_CPPFLAGS)
+tests_efl_js_eina_js_containers_suite_LDADD = \
+@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EFL_JS_LIBS@
+tests_efl_js_eina_js_containers_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@
+
+tests_efl_js_ecore_js_suite_SOURCES = \
+tests/efl_js/ecore_js_suite.cc
+
+tests_efl_js_ecore_js_suite_CPPFLAGS = $(SUITE_RUNNER_CPPFLAGS)
+tests_efl_js_ecore_js_suite_LDADD = \
+@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EFL_JS_LIBS@
+tests_efl_js_ecore_js_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@
+
+tests_efl_js_eldbus_js_suite_SOURCES = \
+tests/efl_js/eldbus_js_suite.cc
+
+tests_efl_js_eldbus_js_suite_CPPFLAGS = $(SUITE_RUNNER_CPPFLAGS)
+tests_efl_js_eldbus_js_suite_LDADD = \
+@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EFL_JS_LIBS@
+tests_efl_js_eldbus_js_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@
+
+tests_efl_js_ethumb_js_suite_SOURCES = \
+tests/efl_js/ethumb_js_suite.cc
+
+tests_efl_js_ethumb_js_suite_CPPFLAGS = $(SUITE_RUNNER_CPPFLAGS)
+tests_efl_js_ethumb_js_suite_LDADD = \
+@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EFL_JS_LIBS@
+tests_efl_js_ethumb_js_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@
+
+tests_efl_js_eio_js_suite_SOURCES = \
+tests/efl_js/eio_js_suite.cc
+
+tests_efl_js_eio_js_suite_CPPFLAGS = $(SUITE_RUNNER_CPPFLAGS)
+tests_efl_js_eio_js_suite_LDADD = \
+@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EFL_JS_LIBS@
+tests_efl_js_eio_js_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@
+
+tests_efl_js_benchmark_js_suite_SOURCES = \
+tests/efl_js/benchmark_js_suite.cc
+
+tests_efl_js_benchmark_js_suite_CPPFLAGS = $(SUITE_RUNNER_CPPFLAGS)
+tests_efl_js_benchmark_js_suite_LDADD = \
+@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EFL_JS_LIBS@
+tests_efl_js_benchmark_js_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@
+endif
+endif
+
+
+endif
index 70ef18a..e9f7c13 100644 (file)
@@ -14,6 +14,7 @@ bindings/eina_cxx/eina_clone_allocators.hh       \
 bindings/eina_cxx/eina_error.hh     \
 bindings/eina_cxx/eina_eo_concrete_fwd.hh     \
 bindings/eina_cxx/eina_fold.hh     \
+bindings/eina_cxx/eina_function.hh     \
 bindings/eina_cxx/eina_inarray.hh  \
 bindings/eina_cxx/eina_inlist.hh   \
 bindings/eina_cxx/eina_integer_sequence.hh \
@@ -21,7 +22,9 @@ bindings/eina_cxx/eina_iterator.hh \
 bindings/eina_cxx/eina_lists_auxiliary.hh \
 bindings/eina_cxx/eina_list.hh \
 bindings/eina_cxx/eina_log.hh \
+bindings/eina_cxx/eina_logical.hh \
 bindings/eina_cxx/eina_optional.hh \
+bindings/eina_cxx/eina_pp.hh \
 bindings/eina_cxx/eina_ptrarray.hh \
 bindings/eina_cxx/eina_ptrlist.hh \
 bindings/eina_cxx/eina_range_types.hh \
@@ -31,6 +34,7 @@ bindings/eina_cxx/eina_string_view.hh \
 bindings/eina_cxx/eina_thread.hh \
 bindings/eina_cxx/eina_throw.hh \
 bindings/eina_cxx/eina_tuple.hh \
+bindings/eina_cxx/eina_tuple_c.hh \
 bindings/eina_cxx/eina_tuple_unwrap.hh \
 bindings/eina_cxx/eina_type_traits.hh \
 bindings/eina_cxx/eina_value.hh
index f16a4a4..4da5224 100644 (file)
@@ -347,3 +347,14 @@ installed_emotionluadir = $(datadir)/elua/modules/emotion
 nodist_installed_emotionlua_DATA = $(generated_emotion_lua_all)
 
 endif
+
+# TODO: gives undefined reference to emotion_object_class_get()
+if HAVE_JS
+
+generated_emotion_js_bindings = $(emotion_eolian_files:%.eo=%.eo.js.cc)
+
+CLEANFILES += $(generated_emotion_js_bindings)
+
+GENERATED_JS_BINDINGS += $(generated_emotion_js_bindings)
+
+endif
index 57b096e..51924fe 100644 (file)
@@ -197,3 +197,13 @@ endif
 
 
 EXTRA_DIST += tests/eo/eunit_tests.h lib/eo/eo_ptr_indirection.x
+
+if HAVE_JS
+
+generated_eo_js_bindings = $(eo_eolian_files:%.eo=%.eo.js.cc)
+
+CLEANFILES += $(generated_eo_js_bindings)
+
+GENERATED_JS_BINDINGS += $(generated_eo_js_bindings)
+
+endif
diff --git a/src/Makefile_Eolian_Js.am b/src/Makefile_Eolian_Js.am
new file mode 100644 (file)
index 0000000..32cf893
--- /dev/null
@@ -0,0 +1,123 @@
+
+if HAVE_JS
+
+### Binary
+bin_PROGRAMS += bin/eolian_js/eolian_js
+
+bin_eolian_js_eolian_js_SOURCES = \
+    bin/eolian_js/main.cc
+
+bin_eolian_js_eolian_js_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
+-I$(top_srcdir)/src/bin/eolian_js \
+-I$(top_srcdir)/src/bindings/js/eina_js \
+-I$(top_srcdir)/src/bindings/js/eo_js \
+@EOLIAN_JS_CFLAGS@ \
+@EINA_CXX_CFLAGS@ \
+@EOLIAN_CXX_CFLAGS@
+
+bin_eolian_js_eolian_js_LDADD = @USE_EO_LIBS@ @USE_EOLIAN_LIBS@
+bin_eolian_js_eolian_js_DEPENDENCIES = @USE_EO_INTERNAL_LIBS@ @USE_EOLIAN_INTERNAL_LIBS@
+
+include Makefile_Eolian_Js_Helper.am
+
+### Unit tests
+
+if EFL_ENABLE_TESTS
+if HAVE_NODEJS
+
+TESTS += tests/eolian_js/eolian_js_suite.js
+
+check_LTLIBRARIES += tests/eolian_js/libeolian_js_suite.la
+
+tests/eolian_js/eolian_js_suite.js: tests/eolian_js/eolian_js_suite_mod.node
+tests/eolian_js/eolian_js_suite_mod.node: tests/eolian_js/libeolian_js_suite.la
+       $(AM_V_CP)$(CP) $(top_builddir)/src/tests/eolian_js/.libs/libeolian_js_suite.so $(top_builddir)/src/tests/eolian_js/eolian_js_suite_mod.node
+
+tests_eolian_js_libeolian_js_suite_la_SOURCES = \
+tests/eolian_js/eolian_js_suite.cc \
+tests/eolian_js/eolian_js_test_eolian_js_binding.cc \
+tests/eolian_js/eolian_js_test_constructor_method_impl.c \
+tests/eolian_js/eolian_js_test_test_object_impl.c
+
+tests_eolian_js_libeolian_js_suite_la_CPPFLAGS = \
+-I$(top_builddir)/src/lib/efl \
+-I$(top_srcdir)/src/bin/eolian_js \
+-I$(top_srcdir)/src/bindings/js/eina_js \
+-I$(top_srcdir)/src/bindings/js/eo_js \
+-I$(top_builddir)/src/tests/eolian_js \
+-DTESTS_WD=\"`pwd`\" \
+-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eolian_js\" \
+-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)/src/tests/eolian_js\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/eolian_js\" \
+-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eolian_js\" \
+@CHECK_CFLAGS@ @EOLIAN_CXX_CFLAGS@ @EINA_JS_CFLAGS@ @EO_JS_CFLAGS@ \
+@EOLIAN_CFLAGS@ @EINA_CFLAGS@ @EO_CFLAGS@ @ECORE_CFLAGS@ @EINA_CXX_CFLAGS@ \
+@EO_JS_CFLAGS@ @EO_CXX_CFLAGS@
+tests_eolian_js_libeolian_js_suite_la_LIBADD = \
+@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EFL_JS_LIBS@
+tests_eolian_js_libeolian_js_suite_la_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@
+tests_eolian_js_libeolian_js_suite_la_CFLAGS = $(tests_eolian_js_libeolian_js_suite_la_CXXFLAGS)
+tests_eolian_js_libeolian_js_suite_la_LIBTOOLFLAGS = --tag=disable-static
+tests_eolian_js_libeolian_js_suite_la_LDFLAGS = -rpath $(abs_top_builddir)/tests/eolian_js @EFL_LTLIBRARY_FLAGS@
+
+# if compiler_o_lo == yes, lo, otherwise $(OBJEXT)
+
+tests/eolian_js/tests_eolian_js_libeolian_js_suite_la-eolian_js_test_eolian_js_binding.l$(OBJEXT): tests/eolian_js/constructor_method_class.eo.js.cc tests/eolian_js/constructor_method_class.eo.h tests/eolian_js/test_object.eo.js.cc tests/eolian_js/test_object.eo.h
+tests/eolian_js/tests_eolian_js_libeolian_js_suite_la-eolian_js_test_constructor_method_impl.l$(OBJEXT): tests/eolian_js/constructor_method_class.eo.c
+tests/eolian_js/tests_eolian_js_libeolian_js_suite_la-eolian_js_test_test_object_impl.l$(OBJEXT): tests/eolian_js/test_object.eo.c
+
+CLEANFILES += \
+tests/eolian_js/constructor_method_class.eo.js.cc \
+tests/eolian_js/constructor_method_class.eo.c \
+tests/eolian_js/constructor_method_class.eo.h \
+tests/eolian_js/test_object.eo.js.cc \
+tests/eolian_js/test_object.eo.c \
+tests/eolian_js/test_object.eo.h
+else
+check_PROGRAMS += tests/eolian_js/eolian_js_suite
+TESTS += tests/eolian_js/eolian_js_suite
+
+tests_eolian_js_eolian_js_suite_SOURCES = \
+tests/eolian_js/eolian_js_suite.cc \
+tests/eolian_js/eolian_js_test_eolian_js_binding.cc \
+tests/eolian_js/eolian_js_test_constructor_method_impl.c \
+tests/eolian_js/eolian_js_test_test_object_impl.c
+
+tests/eolian_js/tests_eolian_js_eolian_js_suite-eolian_js_test_eolian_js_binding.$(OBJEXT): tests/eolian_js/constructor_method_class.eo.js.cc tests/eolian_js/constructor_method_class.eo.h tests/eolian_js/test_object.eo.js.cc tests/eolian_js/test_object.eo.h
+tests/eolian_js/tests_eolian_js_eolian_js_suite-eolian_js_test_constructor_method_impl.$(OBJEXT): tests/eolian_js/constructor_method_class.eo.c
+tests/eolian_js/tests_eolian_js_eolian_js_suite-eolian_js_test_test_object_impl.$(OBJEXT): tests/eolian_js/test_object.eo.c
+
+CLEANFILES += \
+tests/eolian_js/constructor_method_class.eo.js.cc \
+tests/eolian_js/constructor_method_class.eo.c \
+tests/eolian_js/constructor_method_class.eo.h \
+tests/eolian_js/test_object.eo.js.cc \
+tests/eolian_js/test_object.eo.c \
+tests/eolian_js/test_object.eo.h
+
+tests_eolian_js_eolian_js_suite_CPPFLAGS =     \
+-I$(top_builddir)/src/lib/efl \
+-I$(top_srcdir)/src/bin/eolian_js \
+-I$(top_srcdir)/src/bindings/js/eina_js \
+-I$(top_srcdir)/src/bindings/js/eo_js \
+-I$(top_builddir)/src/tests/eolian_js \
+-I$(top_srcdir)/src/tests/efl_js \
+-DTESTS_WD=\"`pwd`\" \
+-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eolian_js\" \
+-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)/src/tests/eolian_js\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/eolian_js\" \
+-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eolian_js\" \
+@CHECK_CFLAGS@ @EOLIAN_CXX_CFLAGS@ @EINA_JS_CFLAGS@ @EO_JS_CFLAGS@ @EFL_JS_CFLAGS@ \
+@EOLIAN_CFLAGS@ @EINA_CFLAGS@ @EO_CFLAGS@ @ECORE_CFLAGS@ @EINA_CXX_CFLAGS@ \
+@EO_JS_CFLAGS@ @EO_CXX_CFLAGS@ @EFL_JS_CFLAGS@
+
+tests_eolian_js_eolian_js_suite_LDADD = \
+@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ @USE_EFL_JS_LIBS@ @USE_EVAS_LIBS@ @USE_EFL_JS_LIBS@
+tests_eolian_js_eolian_js_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@ @USE_EVAS_INTERNAL_LIBS@ @USE_EFL_JS_INTERNAL_LIBS@
+endif
+endif
+
+endif
+
+
+
diff --git a/src/Makefile_Eolian_Js_Helper.am b/src/Makefile_Eolian_Js_Helper.am
new file mode 100644 (file)
index 0000000..fcc5231
--- /dev/null
@@ -0,0 +1,18 @@
+#if HAVE_EOLIAN_JS
+#EOLIAN_JS = @eolian_js@
+#_EOLIAN_JS_DEP = @eolian_js@
+#else
+EOLIAN_JS = EFL_RUN_IN_TREE=1 $(top_builddir)/src/bin/eolian_js/eolian_js${EXEEXT}
+_EOLIAN_JS_DEP = bin/eolian_js/eolian_js${EXEEXT}
+#endif
+
+AM_V_EOLJS = $(am__v_EOLJS_@AM_V@)
+am__v_EOLJS_ = $(am__v_EOLJS_@AM_DEFAULT_V@)
+am__v_EOLJS_0 = @echo "  EOLJS  " $@;
+
+SUFFIXES += .eo.js.cc
+
+%.eo.js.cc: %.eo $(_EOLIAN_JS_DEP)
+       $(AM_V_EOLJS)$(EOLIAN_JS) $(EOLIAN_FLAGS) -o $@ $<
+
+CLEANFILES += $(BUILT_SOURCES)
index 3f7dd39..ebc5480 100644 (file)
@@ -2221,3 +2221,13 @@ $(NULL)
 
 installed_evasfiltersdir = $(datadir)/evas/filters/lua
 dist_installed_evasfilters_DATA = $(evas_filters_lua)
+
+if HAVE_JS
+
+generated_evas_js_bindings = $(evas_eolian_files:%.eo=%.eo.js.cc)
+
+CLEANFILES += $(generated_evas_js_bindings)
+
+GENERATED_JS_BINDINGS += $(generated_evas_js_bindings)
+
+endif
diff --git a/src/bin/efl_js/efljslaunch b/src/bin/efl_js/efljslaunch
new file mode 100755 (executable)
index 0000000..785c30e
--- /dev/null
@@ -0,0 +1,139 @@
+#!/bin/sh
+':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"
+
+// Core node modules
+var path = require('path');
+var os = require('os');
+var zlib = require('zlib');
+var child_process = require('child_process');
+
+// 3rd party modules
+var fs = require('fs-extra');
+var getopt = require('node-getopt');
+var tar = require('tar');
+
+function make_error_cb(message)
+{
+   return function(e) {
+      console.error("Error %s: %s", message, e);
+      process.exit(1);
+   };
+}
+
+function remove_files(options)
+{
+   if (options.verbose)
+      console.log("Removing temporary files");
+
+   fs.remove(options.project_folder);
+}
+
+function run_project(options)
+{
+   if (options.verbose)
+      console.log("Running the project");
+
+   var current_dir = process.cwd();
+   process.chdir(options.project_root);
+
+   var proc = child_process.fork(options.metadata.Entry);
+   proc.on('exit', function(code){
+      if (options.verbose)
+         console.log('Child exited with code %s', code);
+      process.chdir(current_dir);
+      if (!options.keep)
+         remove_files(options);
+   });
+
+}
+
+function unpack_project_data(options)
+{
+   if (options.verbose)
+      console.log("Unpacking project sources and assets");
+
+   var datafile = path.join(options.project_folder, "data.tar.gz");
+   var project_root = path.join(options.project_folder, "root");
+
+   options.project_root = project_root;
+
+   var input = fs.createReadStream(datafile);
+   var unzipper = zlib.createGunzip();
+   var extractor = tar.Extract({path: project_root, strip: 0});
+
+   input.on('error', make_error_cb("reading package data file."));
+   extractor.on('error', make_error_cb("unpacking package data file."));
+   if (!("only-extract" in options))
+      extractor.on('end', function(){ run_project(options); });
+
+   input.pipe(unzipper)
+   unzipper.pipe(extractor);
+}
+
+function read_metadata(options)
+{
+   if (options.verbose)
+      console.log("Reading project metadata");
+
+   var project_folder = options.project_folder;
+   var metadata = JSON.parse(fs.readFileSync(path.join(project_folder, "meta.json")));
+
+   if (options.verbose)
+      console.log("Project: %s\nVersion: %s\nEntry point: %s", metadata.Name, metadata.Version, metadata.Entry);
+   if ("only-dump" in options)
+      process.exit(0);
+
+   options.metadata = metadata;
+
+   unpack_project_data(options);
+}
+
+function extract(filename, options)
+{
+   if (options.verbose)
+      console.log("Extracting ", filename, "with options ", options);
+
+   var project_id = path.basename(filename, ".epk");
+   var project_folder = path.join(options['temp-dir'], project_id);
+
+   options.project_folder = project_folder;
+   options.project_id = project_id;
+
+   var input = fs.createReadStream(filename);
+   var extractor = tar.Extract({path: options['temp-dir'], strip: 0});
+
+   input.on('error', make_error_cb("reading package file."));
+   extractor.on('error', make_error_cb("unpacking package file."));
+   extractor.on('end', function(){ read_metadata(options); });
+
+   input.pipe(extractor);
+}
+
+function main() {
+   var options = getopt.create([
+       ['d', 'only-dump', 'Only dump information about the package'],
+       ['e', 'only-extract', 'Only extract the package, do not run'],
+       ['h', 'help', 'Display this help'],
+       ['k', 'keep', 'Do not remove the files after exiting'],
+       ['t', 'temp-dir=ARG', 'Temporary dir to extract files'],
+       ['v', 'verbose', 'Print information messages'],
+   ]).bindHelp().parseSystem();
+
+   var filename = options.argv[0];
+   if (filename === undefined)
+     {
+        console.error("Must provide a package file.");
+        process.exit(1);
+     }
+
+   if (!('temp-dir' in options.options))
+     {
+        options.options["temp-dir"] = path.join(os.tmpdir(), "efljs_apps");
+        if (options.verbose)
+         console.log("Defaulting temp dir to ", options.options["temp-dir"]);
+     }
+
+   extract(filename, options.options);
+}
+
+main();
diff --git a/src/bin/efl_js/efljslaunch.desktop b/src/bin/efl_js/efljslaunch.desktop
new file mode 100644 (file)
index 0000000..53371cb
--- /dev/null
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=EFL JS package launcher
+Exec=efljslaunch %f
+Type=Application
+Categories=EFL
+Terminal=true
+MimeType=application/x-efljspackage;
diff --git a/src/bin/efl_js/efljslaunch.xml b/src/bin/efl_js/efljslaunch.xml
new file mode 100644 (file)
index 0000000..b1db684
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+    <mime-type type="application/x-efljspackage">
+        <comment xml:lang="en">EFL JS package</comment>
+        <glob pattern="*.epk"/>
+    </mime-type>
+</mime-info>
\ No newline at end of file
diff --git a/src/bin/efl_js/efljspack b/src/bin/efl_js/efljspack
new file mode 100755 (executable)
index 0000000..50e27b6
--- /dev/null
@@ -0,0 +1,251 @@
+#!/bin/sh
+':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"
+
+var zlib = require('zlib');
+var path = require('path');
+
+// external dependencies
+var fs = require('fs-extra');
+var tar = require('tar');
+var fstream = require('fstream');
+var getopt = require('node-getopt');
+
+/*
+ * Packing a project.
+ * The efljs package has a similar format to debian packages. It is a
+ * tar package containing two files:
+ *
+ * meta.txt: Metadata information about this package.
+ * data.tar.gz: Gzipped data, with the project tree ready to be decompressed
+ *              and run by the package launcher.
+ *
+ * During the build, a out/ directory is created in the project root to
+ * store the package and temporary files.
+ */
+
+// Creates a stub .project file and packs it.
+function pack_single(sourcepath, options)
+{
+   if (options.verbose)
+      console.log("Creating project file for single file app", sourcepath);
+
+   var dir_name = path.dirname(fs.realpathSync(sourcepath));
+   var filename = path.basename(sourcepath);
+   var projectRegex = /^(.*).js$/g;
+   var project_name = projectRegex.exec(filename)[1];
+
+   if (!validade_project_name(project_name))
+     {
+        console.error("Invalid project name. Must start with a letter.");
+        process.exit(0);
+     }
+
+   var project_filename = path.join(dir_name, project_name + ".project");
+
+   var fd = fs.openSync(project_filename, 'w');
+
+   var jsonData = {};
+
+   jsonData["Name"] = project_name;
+   jsonData["Entry"] = filename;
+   jsonData["Sources"] = [[filename, '.']];
+   jsonData["Version"] = "0.1";
+
+   fs.writeSync(fd, JSON.stringify(jsonData, null, 2));
+
+   fs.closeSync(fd);
+
+   pack_project(project_filename, options);
+
+}
+
+function generate_build_info(configuration, project_file, options)
+{
+   build_info = {};
+
+   // project == project_dir
+   //        /out == build_dir
+   //            /data == data_dir
+   //            /name-version == package_dir
+
+   build_info.package_id = configuration.Name + "-" + configuration.Version;
+   build_info.project_dir = path.dirname(project_file);
+   build_info.build_dir = path.join(build_info.project_dir, "out");
+   build_info.data_dir = path.join(build_info.build_dir, "data");
+   build_info.package_dir = path.join(build_info.build_dir, build_info.package_id);
+   build_info.data_file = path.join(build_info.package_dir, "data.tar.gz");
+   build_info.package_file = path.join(build_info.build_dir, build_info.package_id + ".epk")
+   build_info.metadata_file = path.join(build_info.package_dir, "meta.json");
+
+   if (options.verbose)
+     {
+        console.log("Project id: ", build_info.package_id);
+        console.log("Project source dir: ", build_info.project_dir);
+        console.log("Project build dir: ", build_info.build_dir);
+        console.log("Project data dir:", build_info.data_dir);
+        console.log("Project package dir:", build_info.package_dir);
+     }
+
+   return build_info;
+
+}
+
+// Project names must start with a letter and contain only
+// letters, digits and underscores.
+function validade_project_name(name)
+{
+   return (/^[a-zA-Z][\w-]*$/).test(name)
+}
+
+function pack_project(project_file, options)
+{
+   if (options.verbose)
+      console.log("Packing project from project file ", project_file);
+
+   var configuration = JSON.parse(fs.readFileSync(project_file));
+
+   if (!validade_project_name(configuration.Name))
+     {
+        console.error("Invalid project name. Must start with a letter.");
+        process.exit(0);
+     }
+
+   var build_info = generate_build_info(configuration, project_file, options);
+
+   try
+     {
+        fs.mkdirSync(build_info.build_dir);
+        fs.mkdirSync(build_info.data_dir);
+        fs.mkdirSync(build_info.package_dir);
+     }
+   catch (e)
+     {
+        console.warn("Warning: Project output directories not empty.");
+     }
+
+   create_metadata_file(configuration, build_info, options);
+
+   // If not explicitly named on configuration, add the entire directory
+   if (!('Sources' in configuration))
+     {
+        generate_source_list(configuration, build_info.project_dir, options);
+     }
+
+   create_project_tree(configuration.Sources, build_info, options);
+
+   pack_data_dir(build_info, options);
+}
+
+function create_project_tree(sources, build_info, options)
+{
+   for (var i = sources.length - 1; i >= 0; i--) {
+      if (options.verbose)
+         console.log("Adding file ", sources[i], "to package.");
+      var source_file = path.join(build_info.project_dir, sources[i][0]);
+      var destination_dir = path.join(build_info.data_dir, sources[i][1]);
+      var destination_filename = path.basename(source_file);
+      var destination_file = path.join(destination_dir, destination_filename);
+
+      fs.copySync(source_file, destination_file);
+   };
+}
+
+function generate_source_list(configuration, project_dir, options)
+{
+   console.log("Generating source list for project dir", build_info.project_dir);
+   var dir_entries = fs.readdirSync(project_dir);
+   var sources = [];
+
+   dir_entries.forEach(function(entry){
+      if (entry == "out")
+         return;
+      sources.push([entry, "."]);
+   });
+   configuration.Sources = sources;
+}
+
+function create_metadata_file(configuration, build_info, options)
+{
+   if (options.verbose)
+      console.log("Creating metadata file", build_info.metadata_file);
+
+   var metadata = {};
+
+   metadata.Name = configuration.Name;
+   metadata.Entry = configuration.Entry;
+   metadata.Version = configuration.Version;
+
+   var output = fs.createWriteStream(build_info.metadata_file);
+   output.write(JSON.stringify(metadata, null, 2));
+   output.close();
+}
+
+function pack_data_dir(build_info, options)
+{
+   if (options.verbose)
+      console.log("Packing data...");
+
+   pack_directory(build_info.data_dir, build_info.data_file, true, true, function(){
+      if (options.verbose)
+         console.log("Packed data");
+      pack_final_package(build_info, options);
+   });
+}
+
+function pack_final_package(build_info, options)
+{
+   if (options.verbose)
+      console.log("Creating package ", build_info.package_file);
+   pack_directory(build_info.package_dir, build_info.package_file, false, false, function(){
+      if (options.verbose)
+         console.log("Created project package.");
+   });
+}
+
+function pack_directory(source_dir, target_file, strip_base_dir, should_gzip, callback)
+{
+   var output = fs.createWriteStream(target_file);
+   var packer = tar.Pack({fromBase: strip_base_dir == true});
+   if (callback != undefined)
+      output.on('close', callback);
+
+   var reader = fstream.Reader({path: source_dir, type: "Directory"});
+   var destStr = reader.pipe(packer);
+   if(should_gzip)
+      destStr = destStr.pipe(zlib.createGzip());
+   destStr.pipe(output);
+}
+
+function main()
+{
+
+   var options = getopt.create([
+      ['v', 'verbose', 'Explain what is being done'],
+      ['h', 'help', 'Display this help']
+   ]).bindHelp().parseSystem();
+
+   filename = options.argv[0];
+
+   if (typeof filename === 'undefined')
+     {
+        console.error('Must provide a valid js or project file.');
+        process.exit(1);
+     }
+
+   if (endsWith(filename, ".js"))
+     {
+        pack_single(filename, options.options);
+     }
+   else if (endsWith(filename, ".project"))
+     {
+        pack_project(filename, options.options);
+     }
+}
+
+main();
+
+//// Helper functions
+function endsWith(str, suffix)
+{
+    return str.indexOf(suffix, str.length - suffix.length) !== -1;
+}
diff --git a/src/bin/efl_js/launcher_main.cc b/src/bin/efl_js/launcher_main.cc
new file mode 100644 (file)
index 0000000..680f16c
--- /dev/null
@@ -0,0 +1,156 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <cerrno>
+
+#include <Eo_Js.hh>
+#include <Eina.hh>
+#include <Eo.hh>
+// #include <efl_js.hh>
+
+using namespace std;
+using namespace v8;
+
+const char PATH_SEPARATOR =
+#ifdef _WIN32
+    '\\';
+#else
+    '/';
+#endif
+
+static std::string get_file_contents(const char *filename) {
+    std::ifstream in(filename, std::ios::in);
+    if (in) {
+        std::ostringstream contents;
+        contents << in.rdbuf();
+        in.close();
+        return contents.str();
+    } else {
+        throw(errno);
+    }
+}
+
+static std::string get_filename(std::string path)
+{
+    int beginIdx = path.rfind(PATH_SEPARATOR);
+    return path.substr(beginIdx + 1);
+}
+
+static void show_usage(std::string name)
+{
+    std::cerr << "Usage: " << get_filename(name) << " <option(s)> [SOURCE]\n" << std::endl
+              << "Options:" << std::endl
+              << "\t-h, --help\t\t Show this help message" << std::endl;
+}
+
+/*
+ * Basic console.log implementation with space-separated values,
+ * no substitution
+ */
+void Log(const FunctionCallbackInfo<Value>& args)
+{
+    Isolate* isolate = Isolate::GetCurrent();
+    HandleScope scope(isolate);
+
+    for (int i=0; i < args.Length(); i++)
+    {
+        if (i != 0)
+            std::cout << " ";
+        String::Utf8Value string(args[i]);
+        std::cout << *string;
+    }
+
+    std::cout << std::endl;
+
+    args.GetReturnValue().Set(v8::Null(isolate));
+}
+
+
+int main(int argc, char* argv[])
+{
+
+    std::string script_source;
+    char *filename = 0;
+
+    for (int i=1; i < argc; i++)
+    {
+        if ((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "--help") == 0))
+        {
+            show_usage(argv[0]);
+            return 0;
+        }
+        else
+        {
+            filename = argv[i];
+        }
+    }
+
+    if (!filename)
+    {
+        std::cerr << "Error: No source provided." << std::endl;
+        show_usage(argv[0]);
+        return 1;
+    }
+
+    try
+    {
+        script_source = get_file_contents(filename);
+    } catch (int errno)
+    {
+        perror("Error: ");
+        return 1;
+    }
+
+
+    efl::eina::js::compatibility_initialize();
+    v8::V8::SetFlagsFromCommandLine(&argc, const_cast<char**>(argv), true);
+
+    v8::Isolate* isolate = efl::eina::js::compatibility_isolate_new();
+    {
+        Isolate::Scope isolate_scope(isolate);
+        HandleScope handleScope(isolate);
+
+        Local<Context> context = Context::New(isolate, NULL);
+        Context::Scope context_scope(context);
+        context->Enter();
+
+        // Setup the console and log
+        Local<Object> console = Object::New(isolate);
+        Local<FunctionTemplate> log = FunctionTemplate::New(isolate, Log);
+        console->Set(String::NewFromUtf8(isolate, "log"), log->GetFunction());
+
+        Local<Object> global = context->Global();
+        global->Set(String::NewFromUtf8(isolate, "console"), console);
+
+        // Set up the efl exports; Needed to enter the context before this
+        // due to creating Objects instead of Objects Templates
+        // WIP: Commented out due to potential missing v8 platform implementation issues
+        // Local<Object> efl_exports = Object::New(isolate);
+        // global->Set(String::NewFromUtf8(isolate, "efl"), efl_exports);
+        // efl_js::init(efl_exports);
+
+        // And now the user's script
+        Local<String> source = String::NewFromUtf8(isolate, script_source.c_str());
+
+        Local<Script> script = Script::Compile(source);
+
+        TryCatch tryCatch(isolate);
+        Local<Value> result = script->Run();
+
+        if (result.IsEmpty())
+        {
+            Local<Value> exception = tryCatch.Exception();
+            String::Utf8Value exception_str(exception);
+            printf("Exception: %s\n", *exception_str);
+        }
+
+    }
+
+    V8::Dispose();
+    return 0;
+}
diff --git a/src/bin/eolian_js/.gitignore b/src/bin/eolian_js/.gitignore
new file mode 100644 (file)
index 0000000..631f68a
--- /dev/null
@@ -0,0 +1 @@
+/eolian_js
diff --git a/src/bin/eolian_js/eolian/class.hh b/src/bin/eolian_js/eolian/class.hh
new file mode 100644 (file)
index 0000000..bd04d5f
--- /dev/null
@@ -0,0 +1,139 @@
+#ifndef EOLIAN_KLASS_HH
+#define EOLIAN_KLASS_HH
+
+#include <Eina.hh>
+
+#include <eolian/js/domain.hh>
+
+#include <ostream>
+
+inline std::string name(Eolian_Class const* klass)
+{
+  return ::eolian_class_name_get(klass);
+}
+
+inline std::string full_name(Eolian_Class const* klass)
+{
+  return ::eolian_class_full_name_get(klass);
+}
+
+inline std::string full_name_transformed(Eolian_Class const* klass)
+{
+  auto r = full_name(klass);
+  std::replace(r.begin(), r.end(), '.', '_');
+  return r;
+}
+
+inline std::size_t namespace_size(Eolian_Class const* klass)
+{
+   std::size_t size = 0;
+   for(efl::eina::iterator<const char> first (::eolian_class_namespaces_get(klass))
+         , last; first != last; ++first)
+     ++size;
+   return size;
+}
+
+inline std::string type_class_name(Eolian_Type const* tp)
+{
+   if (tp)
+     {
+        Eolian_Type_Type tpt = ::eolian_type_type_get(tp);
+        if (tpt == EOLIAN_TYPE_POINTER || tpt == EOLIAN_TYPE_ALIAS || tpt == EOLIAN_TYPE_REGULAR)
+          {
+             return type_class_name(::eolian_type_base_type_get(tp));
+          }
+        else if(tpt == EOLIAN_TYPE_CLASS)
+          {
+             Eolian_Class const* klass = ::eolian_type_class_get(tp);
+             if (klass)
+               {
+                  Eina_Stringshare* klass_name = ::eolian_class_full_name_get(klass);
+                  if (!klass_name)
+                    throw std::runtime_error("Could not get Eo class name");
+
+                  return klass_name;
+               } // TODO: else should throw std::runtime_error("Could not get Eo class");
+          }
+        else if(tpt == EOLIAN_TYPE_STRUCT)
+          {
+             auto struct_type_full_name = ::eolian_type_full_name_get(tp);
+             if (!struct_type_full_name)
+               throw std::runtime_error("Could not get struct name");
+             return struct_type_full_name;
+          }
+     }
+   return "";
+}
+
+inline void print_lower_case_namespace(Eolian_Class const* klass, std::ostream& os)
+{
+  std::vector<std::string> namespace_;
+   for(efl::eina::iterator<const char> first (::eolian_class_namespaces_get(klass))
+         , last; first != last; ++first)
+     namespace_.push_back(&*first);
+   for(auto first = namespace_.begin(), last = namespace_.end()
+         ; first != last; ++first)
+     {
+       std::string lower(*first);
+       std::transform(lower.begin(), lower.end(), lower.begin(), tolower);
+       os << lower;
+       if(std::next(first) != last) os << "::";
+     }
+}
+
+inline void print_eo_class(Eolian_Class const* klass, std::ostream& os)
+{
+   assert(klass != 0);
+   EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "print_eo_class";
+
+   auto toupper = [] (unsigned char c) { return std::toupper(c); };
+  
+   EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "print_eo_class";
+   std::vector<std::string> namespace_;
+   for(efl::eina::iterator<const char> first (::eolian_class_namespaces_get(klass))
+         , last; first != last; ++first)
+     namespace_.push_back(&*first);
+   EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "namespace";
+   namespace_.push_back(name(klass));
+   EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "class";
+   switch(eolian_class_type_get(klass))
+     {
+     case EOLIAN_CLASS_REGULAR:
+     case EOLIAN_CLASS_ABSTRACT:
+       EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "";
+       namespace_.push_back("CLASS");
+       break;
+     case EOLIAN_CLASS_INTERFACE:
+       EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "";
+       namespace_.push_back("INTERFACE");
+       break;
+     case EOLIAN_CLASS_MIXIN:
+       EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "";
+       namespace_.push_back("MIXIN");
+       break;
+     default:
+       EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "default ?";
+       std::abort();
+     }
+   EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "";
+   for(auto first = namespace_.begin(), last = namespace_.end()
+         ; first != last; ++first)
+     {
+       EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "";
+       std::string upper(*first);
+       std::transform(upper.begin(), upper.end(), upper.begin(), toupper);
+       os << upper;
+       if(std::next(first) != last) os << "_";
+     }
+   EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "";
+}
+
+inline bool is_evas(Eolian_Class const* klass)
+{
+  EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "is_evas";
+  efl::eina::iterator<const char> first (::eolian_class_namespaces_get(klass));
+  return first != efl::eina::iterator<const char>()
+    && std::strcmp(&*first, "Evas") == 0;
+}
+
+#endif
diff --git a/src/bin/eolian_js/eolian/js/domain.hh b/src/bin/eolian_js/eolian/js/domain.hh
new file mode 100644 (file)
index 0000000..38cf542
--- /dev/null
@@ -0,0 +1,8 @@
+
+#include <Eina.hh>
+
+namespace eolian { namespace js {
+
+extern efl::eina::log_domain domain;
+
+} }
diff --git a/src/bin/eolian_js/eolian/js/format.hh b/src/bin/eolian_js/eolian/js/format.hh
new file mode 100644 (file)
index 0000000..a07d541
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef EOLIAN_JS_FORMAT_HH
+#define EOLIAN_JS_FORMAT_HH
+
+#include <eolian/js/domain.hh>
+
+#include <algorithm>
+#include <string>
+#include <cctype>
+
+namespace eolian { namespace js {
+
+namespace format {
+
+std::string generic(std::string const& in)
+{
+   std::string s = in;
+   auto i = s.find('_');
+   while (i != std::string::npos)
+     {
+        if (i <= 0 || i+1 >= s.size() ||
+            !::isalnum(s[i-1]) || !::isalnum(s[i+1]))
+          {
+             EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "Entity '" << in
+               << "' can't be conveniently converted to a JavaScript name.";
+             return in;
+          }
+        s[i+1] = static_cast<char>(::toupper(s[i+1]));
+        s.erase(i, 1);
+        i = s.find('_', i);
+     }
+   return s;
+}
+
+std::string constant(std::string in)
+{
+   std::transform(in.begin(), in.end(), in.begin(), ::toupper);
+   return in;
+}
+
+}
+
+} }
+
+#endif
diff --git a/src/bin/eolian_js/main.cc b/src/bin/eolian_js/main.cc
new file mode 100644 (file)
index 0000000..bc575fd
--- /dev/null
@@ -0,0 +1,1090 @@
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Eolian.h>
+#include <Eina.hh>
+
+#include <eolian/js/domain.hh>
+#include <eolian/js/format.hh>
+#include <eolian/class.hh>
+
+#include <iostream>
+#include <fstream>
+#include <unordered_map>
+#include <sstream>
+#include <stdexcept>
+
+#include <libgen.h>
+#include <getopt.h>
+#include <cstdlib>
+#include <vector>
+#include <set>
+
+namespace eolian { namespace js {
+
+efl::eina::log_domain domain("eolian_js");
+
+struct incomplete_complex_type_error : public std::exception
+{
+  explicit incomplete_complex_type_error(std::string const& msg_arg)
+    : msg(msg_arg)
+  {}
+  virtual ~incomplete_complex_type_error() {}
+  virtual const char* what() const noexcept { return msg.c_str(); }
+
+  std::string msg;
+};
+
+} }
+
+
+std::string
+_lowercase(std::string str)
+{
+  transform(begin(str), end(str), begin(str), tolower);
+  return str;
+}
+
+std::string
+_uppercase(std::string str)
+{
+  transform(begin(str), end(str), begin(str), toupper);
+  return str;
+}
+
+std::string
+_class_name_getter(std::string const& caller_class_prefix, std::string class_name)
+{
+  std::replace(class_name.begin(), class_name.end(), '.', '_');
+  return caller_class_prefix + "_" + class_name + "_cls_name_getter";
+}
+
+void
+_final_type_and_type_type_get(Eolian_Type const* tp_in, Eolian_Type const*& tp_out, Eolian_Type_Type& tpt_out)
+{
+  tp_out = tp_in;
+  tpt_out = eolian_type_type_get(tp_in);
+  while ((tpt_out == EOLIAN_TYPE_REGULAR || tpt_out == EOLIAN_TYPE_ALIAS) && !eolian_type_is_extern(tp_out))
+    {
+       auto t = eolian_type_base_type_get(tp_out);
+       // TODO: shouldn't __undefined_type be flagged as external???
+       if (!t || !eolian_type_full_name_get(t) || strcmp(eolian_type_full_name_get(t), "__undefined_type") == 0) break;
+       tp_out = t;
+       tpt_out = eolian_type_type_get(t);
+    }
+}
+
+std::string
+_eolian_type_cpp_type_named_get(const Eolian_Type *tp, std::string const& caller_class_prefix, std::set<std::string>& need_name_getter)
+{
+  const auto is_const = eolian_type_is_const(tp);
+
+  Eolian_Type_Type tpt = EOLIAN_TYPE_UNKNOWN_TYPE;
+  _final_type_and_type_type_get(tp, tp, tpt);
+
+  if (tpt == EOLIAN_TYPE_UNKNOWN_TYPE)
+    return "error";
+
+  std::string result;
+
+   if ((tpt == EOLIAN_TYPE_VOID
+     || tpt == EOLIAN_TYPE_REGULAR
+     || tpt == EOLIAN_TYPE_COMPLEX
+     || tpt == EOLIAN_TYPE_STRUCT
+     || tpt == EOLIAN_TYPE_STRUCT_OPAQUE
+     || tpt == EOLIAN_TYPE_ENUM
+     || tpt == EOLIAN_TYPE_ALIAS
+     || tpt == EOLIAN_TYPE_CLASS)
+     && is_const)
+     {
+        result += "const ";
+     }
+
+
+   if (tpt == EOLIAN_TYPE_REGULAR
+    || tpt == EOLIAN_TYPE_COMPLEX
+    || tpt == EOLIAN_TYPE_STRUCT
+    || tpt == EOLIAN_TYPE_STRUCT_OPAQUE
+    || tpt == EOLIAN_TYPE_ENUM
+    || tpt == EOLIAN_TYPE_ALIAS
+    || tpt == EOLIAN_TYPE_CLASS)
+     {
+        for (efl::eina::iterator<const char> first(::eolian_type_namespaces_get(tp)), last; first != last; ++first)
+          {
+            std::string np(&*first);
+            result += np + "_"; // TODO: transform it to the C++ equivalent?
+          }
+
+        // this comes from ctypes at eo_lexer.c and KEYWORDS at eo_lexer.h
+        const static std::unordered_map<std::string, std::string> type_map = {
+          {"byte", "signed char"},
+          {"ubyte", "unsigned char"},
+          {"char", "char"},
+          {"short", "short"},
+          {"ushort", "unsigned short"},
+          {"int", "int"},
+          {"uint", "unsigned int"},
+          {"long", "long"},
+          {"ulong", "unsigned long"},
+          {"llong", "long long"},
+          {"ullong", "unsigned long long"},
+          {"int8", "int8_t"},
+          {"uint8", "uint8_t"},
+          {"int16", "int16_t"},
+          {"uint16", "uint16_t"},
+          {"int32", "int32_t"},
+          {"uint32", "uint32_t"},
+          {"int64", "int64_t"},
+          {"uint64", "uint64_t"},
+          {"int128", "int128_t"},
+          {"uint128", "uint128_t"},
+          {"size", "size_t"},
+          {"ssize", "ssize_t"},
+          {"intptr", "intptr_t"},
+          {"uintptr", "uintptr_t"},
+          {"ptrdiff", "ptrdiff_t"},
+          {"time", "time_t"},
+          {"float", "float"},
+          {"double", "double"},
+          {"bool", "Eina_Bool"},
+          {"void", "void"},
+          {"generic_value", "Eina_Value"},
+          {"accessor", "Eina_Accessor"},
+          {"array", "Eina_Array"},
+          {"iterator", "Eina_Iterator"},
+          {"hash", "Eina_Hash"},
+          {"list", "Eina_List"}
+        };
+
+        std::string type_name = eolian_type_name_get(tp);
+        auto it = type_map.find(type_name);
+        if (it != end(type_map))
+          type_name = it->second;
+        result += type_name;
+
+        if (tpt == EOLIAN_TYPE_STRUCT)
+          {
+             result = "efl::eina::js::make_struct_tag<" + result + ">";
+          }
+     }
+   else if (tpt == EOLIAN_TYPE_VOID)
+     result += "void";
+   else // tpt == EOLIAN_TYPE_POINTER
+     {
+        auto btp = eolian_type_base_type_get(tp);
+        result += _eolian_type_cpp_type_named_get(btp, caller_class_prefix, need_name_getter);
+
+        const auto base_is_const = eolian_type_is_const(btp);
+
+        Eolian_Type_Type btpt = EOLIAN_TYPE_UNKNOWN_TYPE;
+        _final_type_and_type_type_get(btp, btp, btpt);
+
+        if (btpt == EOLIAN_TYPE_STRUCT)
+          {
+             std::string f = "::make_struct_tag";
+             auto p = result.find(f);
+             if (p == std::string::npos)
+               throw std::runtime_error("missing struct type tag");
+             result.replace(p, f.size(), "::make_struct_ptr_tag");
+             result.pop_back();
+             result += " *";
+             if (is_const) result += " const";
+             result += ">";
+          }
+        else
+          {
+             if (btpt != EOLIAN_TYPE_POINTER || base_is_const)
+                result += ' ';
+             result += '*';
+             if (is_const) result += " const";
+          }
+
+        if (btpt == EOLIAN_TYPE_COMPLEX)
+          {
+             result = "efl::eina::js::make_complex_tag<" + result;
+
+             bool has_subtypes = false;
+             auto subtypes = eolian_type_subtypes_get(btp);
+             const Eolian_Type *subtype;
+             EINA_ITERATOR_FOREACH(subtypes, subtype)
+               {
+                 auto t = _eolian_type_cpp_type_named_get(subtype, caller_class_prefix, need_name_getter);
+                 auto k = type_class_name(subtype);
+                 if (!k.empty())
+                   {
+                      result += ", " + t + ", " + _class_name_getter(caller_class_prefix, k);
+                      need_name_getter.insert(k);
+                   }
+                 else
+                   {
+                      result += ", " + t + ", ::efl::eina::js::nonclass_cls_name_getter";
+                   }
+                 has_subtypes = true;
+               }
+
+             if (!has_subtypes)
+               throw eolian::js::incomplete_complex_type_error("Incomplete complex type");
+
+             result += ">";
+          }
+     }
+
+   /*if (!name.empty())
+     {
+        if (tpt != EOLIAN_TYPE_POINTER)
+          result += ' ';
+        result += name;
+     }*/
+
+   return result;
+}
+
+using ParametersIterator = efl::eina::iterator<const ::Eolian_Function_Parameter>;
+
+std::vector<const ::Eolian_Function_Parameter*>
+_eolian_function_keys_get(const Eolian_Function *function_id, Eolian_Function_Type ftype)
+{
+  std::vector<const ::Eolian_Function_Parameter*> keys;
+
+  for(ParametersIterator it(::eolian_property_keys_get(function_id, ftype)), last; it != last; ++it)
+    keys.push_back(&*it);
+
+  return keys;
+}
+
+std::vector<const ::Eolian_Function_Parameter*>
+_eolian_function_parameters_get(const Eolian_Function *function_id, Eolian_Function_Type function_type)
+{
+  std::vector<const ::Eolian_Function_Parameter*> parameters;
+
+  ParametersIterator it { (function_type == EOLIAN_METHOD) ?
+                            ::eolian_function_parameters_get(function_id) :
+                            ::eolian_property_values_get(function_id, function_type)
+    }, last;
+
+  for(; it != last; ++it)
+    parameters.push_back(&*it);
+
+  return parameters;
+}
+
+bool
+_function_return_is_missing(Eolian_Function const* func, Eolian_Function_Type func_type)
+{
+   // XXX This function shouldn't exist. Eolian should
+   //     forge functions a priori. Bindings generators
+   //     shouldn't be required to convert such thing.
+   Eolian_Type const* type =
+     ::eolian_function_return_type_get(func, func_type);
+   return !type;
+}
+
+void separate_functions(Eolian_Class const* klass, Eolian_Function_Type t, bool ignore_constructors,
+                        std::vector<Eolian_Function const*>& constructor_functions,
+                        std::vector<Eolian_Function const*>& normal_functions)
+{
+   efl::eina::iterator<Eolian_Function> first ( ::eolian_class_functions_get(klass, t) )
+     , last;
+   for(; first != last; ++first)
+     {
+        Eolian_Function const* function = &*first;
+        if(eolian_function_scope_get(function) == EOLIAN_SCOPE_PUBLIC)
+          {
+             EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << ::eolian_function_full_c_name_get(function, t, EINA_FALSE);
+             if(strcmp("elm_obj_entry_input_panel_imdata_get", ::eolian_function_full_c_name_get(function, t, EINA_FALSE)) != 0 &&
+                !eolian_function_is_beta(function) &&
+                // strcmp("data_callback", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("property", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("part_text_anchor_geometry_get", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("children_iterator_new", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("inputs_get", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("constructor", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("render_updates", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("render2_updates", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("event_callback_priority_add", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("event_callback_array_priority_add", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("event_callback_array_del", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("event_callback_call", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("event_callback_forwarder_add", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("event_callback_forwarder_del", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
+                strcmp("event_callback_del", ::eolian_function_name_get(function)) != 0)
+               {
+                  if( ::eolian_function_is_constructor(function, klass))
+                    {
+                       if(!ignore_constructors)
+                         {
+                             EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "is a constructor";
+                             constructor_functions.push_back(function);
+                         }
+                       else
+                         {
+                            EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "ignoring parent's constructors";
+                         }
+                    }
+                  else /*if( std::strcmp( ::eolian_function_full_c_name_get(function, t, EINA_FALSE)
+                         , "eo_parent") != 0)*/
+                    {
+                       EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "is a NOT constructor "
+                                                                 << ::eolian_function_full_c_name_get(function, t, EINA_FALSE);
+                       normal_functions.push_back(function);
+                    }
+                  // else
+                  //   {
+                  //     EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "parent_set as first constructor";
+                  //     constructor_functions.insert(constructor_functions.begin(), function);
+                  //     normal_functions.push_back(function);
+                  //   }
+               }
+          }
+     }
+}
+
+int main(int argc, char** argv)
+{
+  namespace format = eolian::js::format;
+
+  std::vector<std::string> include_paths;
+  std::string out_file, in_file;
+
+  efl::eina::eina_init eina_init;
+  struct eolian_init
+  {
+    eolian_init() { ::eolian_init(); }
+    ~eolian_init() { ::eolian_shutdown(); }
+  } eolian_init;
+
+  const struct option long_options[] =
+    {
+       { "in",        required_argument, 0,  'I' },
+       { "out-file",  required_argument, 0,  'o' },
+       { "version",   no_argument,       0,  'v' },
+       { "help",      no_argument,       0,  'h' },
+       { 0,           0,                 0,   0  }
+    };
+   const char* options = "I:D:o:c:arvh";
+
+   // get command line options
+   int c, idx;
+   while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1)
+     {
+        if (c == 'I')
+          {
+            include_paths.push_back(optarg);
+          }
+        else if (c == 'o')
+          {
+            if(!out_file.empty())
+              {
+                // _usage(argv[0]);
+                return 1;
+              }
+            out_file = optarg;
+          }
+        else if (c == 'h')
+          {
+             // _usage(argv[0]);
+            return 1;
+          }
+        else if (c == 'v')
+          {
+             // _print_version();
+             // if (argc == 2) exit(EXIT_SUCCESS);
+          }
+     }
+
+   if (optind == argc-1)
+     {
+        in_file = argv[optind];
+     }
+
+   // Add include paths to eolian library
+   for(auto src : include_paths)
+     if (!::eolian_directory_scan(src.c_str()))
+       {
+         EINA_CXX_DOM_LOG_WARN(eolian::js::domain)
+           << "Couldn't load eolian from '" << src << "'.";
+       }
+   if (!::eolian_all_eot_files_parse())
+     {
+       EINA_CXX_DOM_LOG_WARN(eolian::js::domain)
+         << "Eolian failed parsing eot files";
+       assert(false && "Error parsing eot files");
+     }
+   if (!::eolian_file_parse(in_file.c_str()))
+     {
+       EINA_CXX_DOM_LOG_WARN(eolian::js::domain)
+         << "Failed parsing: " << in_file << ".";
+       assert(false && "Error parsing input file");
+     }
+
+   // Create filename path for output
+   std::string file_basename;
+   const Eolian_Class *klass = NULL;
+   {
+     char* dup = strdup(in_file.c_str());
+     char *bn = basename(dup);
+     klass = ::eolian_class_get_by_file(bn);
+     file_basename = bn;
+     free(dup);
+   }
+   if(!klass)
+     {
+       EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "could not find any class defined in this eo file";
+       return -1;
+     }
+
+   std::vector<Eolian_Function const*> constructor_functions;
+   std::vector<Eolian_Function const*> normal_functions;
+
+   std::set<Eolian_Class const*> classes;
+
+   // separate normal functions from constructors for all methods and properties
+   separate_functions(klass, EOLIAN_METHOD, false, constructor_functions, normal_functions);
+   separate_functions(klass, EOLIAN_PROPERTY, false, constructor_functions, normal_functions);
+
+   EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "functions were separated";
+
+   // function to iterate through all inheritance class
+   std::function<void(Eolian_Class const*, std::function<void(Eolian_Class const*)>)>
+     recurse_inherits
+     = [&] (Eolian_Class const* klass, std::function<void(Eolian_Class const*)> function)
+     {
+       for(efl::eina::iterator<const char> first ( ::eolian_class_inherits_get(klass))
+             , last; first != last; ++first)
+         {
+           EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << &*first << std::endl;
+           Eolian_Class const* base = ::eolian_class_get_by_name(&*first);
+           function(base);
+           recurse_inherits(base, function);
+         }
+     };
+
+   // save functions from all inhehritance
+   auto save_functions = [&](Eolian_Class const* klass)
+     {
+       if(classes.find(klass) == classes.end())
+         {
+           classes.insert(klass);
+           separate_functions(klass, EOLIAN_METHOD, true, constructor_functions, normal_functions);
+           separate_functions(klass, EOLIAN_PROPERTY, true, constructor_functions, normal_functions);
+         }
+     };
+   // save functions from all inheritance class without constructors
+   recurse_inherits(klass, save_functions);
+
+   EINA_CXX_DOM_LOG_DBG(eolian::js::domain) << "inherits were recursed";
+
+   std::ofstream os (out_file.c_str());
+   if(!os.is_open())
+     {
+       EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "Couldn't open output file " << out_file;
+       return -1;
+     }
+
+   EINA_CXX_DOM_LOG_DBG(eolian::js::domain) << "output was opened";
+
+   std::string class_name(name(klass)),
+               class_full_name(full_name(klass)),
+               upper_case_class_name(_uppercase(class_name)),
+               lower_case_class_name(_lowercase(class_name));
+
+   // Start preamble generation
+   if (getenv("EFL_RUN_IN_TREE"))
+     {
+       os << "#ifdef HAVE_CONFIG_H\n";
+       os << "#include \"config.h\"\n";
+       os << "#endif\n";
+
+       os << "#include <Efl.h>\n";
+       os << "#include <Ecore.h>\n";
+       os << "#include <Eo.h>\n\n";
+     }
+   else
+     {
+       os << "#ifdef HAVE_CONFIG_H\n";
+       os << "#include \"elementary_config.h\"\n";
+       os << "#endif\n";
+
+       os << "#include <Efl.h>\n";
+       os << "#include <Ecore.h>\n";
+       os << "#include <Eo.h>\n";
+       os << "#include <Evas.h>\n";
+       os << "#include <Edje.h>\n";
+
+       os << "#include <Elementary.h>\n\n";
+       os << "extern \"C\" {\n";
+       os << "#include <elm_widget.h>\n";
+       os << "}\n\n";
+     }
+   os << "#include <Eina_Js.hh>\n\n";
+   os << "#include <Eo_Js.hh>\n\n";
+   os << "#ifdef EAPI\n";
+   os << "# undef EAPI\n";
+   os << "#endif\n";
+
+   os << "#ifdef _WIN32\n";
+   os << "# define EAPI __declspec(dllimport)\n";
+   os << "#else\n";
+   os << "# ifdef __GNUC__\n";
+   os << "#  if __GNUC__ >= 4\n";
+   os << "#   define EAPI __attribute__ ((visibility(\"default\")))\n";
+   os << "#  else\n";
+   os << "#   define EAPI\n";
+   os << "#  endif\n";
+   os << "# else\n";
+   os << "#  define EAPI\n";
+   os << "# endif\n";
+   os << "#endif /* ! _WIN32 */\n\n";
+   os << "extern \"C\" {\n";
+
+   // generate include for necessary headers
+   if(is_evas(klass))
+     os << "#include <Evas.h>\n";
+
+   auto includes_fun = [&os] (Eolian_Class const* klass)
+     {
+       os << "#include <" << eolian_class_file_get(klass) << ".h>\n\n";
+     };
+   // generate include for all inheritance
+   recurse_inherits(klass, includes_fun);
+   os << "#include <" << eolian_class_file_get(klass) << ".h>\n\n";
+
+   os << "}\n\n";
+
+   os << "#ifdef _WIN32\n";
+   os << "# undef EAPI\n";
+   os << "# define EAPI __declspec(dllexport)\n";
+   os << "#endif /* ! _WIN32 */\n\n";
+   
+   os << "#include <array>\n\n";
+
+   EINA_CXX_DOM_LOG_DBG(eolian::js::domain) << "includes added";
+
+   // generate open namespaces
+   if(namespace_size(klass))
+     {
+       std::string space = "";
+       for(efl::eina::iterator<const char> first(::eolian_class_namespaces_get(klass)), last; first != last; ++first)
+         {
+           std::string lower(_lowercase(&*first));
+           os << "namespace " << lower << " {" << space;
+           space = " ";
+         }
+
+       os << "\n";
+     }
+
+   // generate event map
+   std::string event_map = class_name;
+   event_map += "_ev_info_map";
+
+   os << "namespace {\n";
+   os << "::efl::eo::js::event_information_map " << event_map << ";\n";
+   os << "}\n";
+
+   EINA_CXX_DOM_LOG_DBG(eolian::js::domain) << "namespace";
+
+   // save functions that need a name getter for structs
+   std::set<std::string> need_name_getter;
+
+   // generate all structs parsed in this file
+   std::stringstream structs_ss;
+   for (efl::eina::iterator<Eolian_Type> first(::eolian_type_structs_get_by_file(file_basename.c_str()))
+        , last; first != last; ++first)
+     {
+        std::stringstream ss;
+        auto tp = &*first;
+        if (::eolian_type_type_get(tp) == EOLIAN_TYPE_STRUCT_OPAQUE)
+          continue;
+
+        auto struct_name = ::eolian_type_name_get(tp);
+        auto struct_type_full_name = ::eolian_type_full_name_get(tp);
+        if (!struct_name || !struct_type_full_name)
+          {
+             EINA_CXX_DOM_LOG_ERR(eolian::js::domain) << "Could not get struct type name";
+             continue;
+          }
+        else if(strcmp(struct_type_full_name, "Eo.Callback_Array_Item") == 0)
+          continue;
+        std::string struct_c_name = struct_type_full_name;
+        std::replace(struct_c_name.begin(), struct_c_name.end(), '.', '_');
+        ss << "  {\n";
+        ss << "    auto fields_func = [](v8::Isolate* isolate_, v8::Local<v8::ObjectTemplate> prototype_)\n";
+        ss << "    {\n";
+        for (efl::eina::iterator<Eolian_Struct_Type_Field> sf(::eolian_type_struct_fields_get(tp))
+             , sf_end; sf != sf_end; ++sf)
+          {
+             auto field_type = ::eolian_type_struct_field_type_get(&*sf);
+             auto field_name = ::eolian_type_struct_field_name_get(&*sf);
+             if (!field_name)
+               {
+                  EINA_CXX_DOM_LOG_ERR(eolian::js::domain) << "Could not get struct field name";
+                  continue;
+               }
+             std::string field_type_tag_name;
+             try
+               {
+                  field_type_tag_name = _eolian_type_cpp_type_named_get(field_type, class_name, need_name_getter);
+               }
+             catch(eolian::js::incomplete_complex_type_error const& e)
+               {
+                  EINA_CXX_DOM_LOG_ERR(eolian::js::domain) << "Exception while generating '" << field_name << "' fielf of '" << struct_type_full_name << "' struct: " << e.what();
+                  continue;
+               }
+             std::string member_ref = struct_c_name;
+             member_ref += "::";
+             member_ref += field_name;
+
+             auto k = type_class_name(field_type);
+             if (!k.empty())
+               {
+                  need_name_getter.insert(k);
+                  k = _class_name_getter(class_name, k);
+               }
+             else
+               {
+                  k = "::efl::eina::js::nonclass_cls_name_getter";
+               }
+             ss << "      prototype_->SetAccessor(::efl::eina::js::compatibility_new<v8::String>(isolate_, \"" << format::generic(field_name) << "\"),\n";
+             ss << "        static_cast<v8::AccessorGetterCallback>(&::efl::eo::js::get_struct_member<" << struct_c_name << ", decltype(" << member_ref << "), &" << member_ref << ", " << k << ">),\n";
+             ss << "        static_cast<v8::AccessorSetterCallback>(&::efl::eo::js::set_struct_member<" << struct_c_name << ", " << field_type_tag_name << ", decltype(" << member_ref << "), &" << member_ref << ", " << k << ">));\n";
+          }
+        ss << "    };\n";
+        ss << "    auto to_export = ::efl::eo::js::get_namespace({";
+        bool comma = false;
+        for (efl::eina::iterator<const char> ns_it(::eolian_type_namespaces_get(tp)), ns_end; ns_it != ns_end; ++ns_it)
+          {
+            if (comma)
+              ss << ", ";
+            comma = true;
+            ss << '"' << format::generic(&*ns_it) << '"';
+          }
+        ss << "}, isolate, global);\n";
+        ss << "    ::efl::eo::js::register_struct<" << struct_c_name << ">(isolate, \""
+           << format::generic(struct_name) << "\", \"" << struct_type_full_name << "\", to_export, fields_func);\n";
+        ss << "  }\n";
+
+        structs_ss << ss.str();
+     }
+
+   // generate register function for V8
+   std::stringstream register_from_constructor_begin_ss;
+   register_from_constructor_begin_ss
+      << "EAPI v8::Local<v8::ObjectTemplate>\n"
+      << "register_" << lower_case_class_name << "_from_constructor\n"
+      << "(v8::Isolate* isolate, v8::Handle<v8::FunctionTemplate> constructor, ::efl::eina::js::global_ref<v8::Function>* constructor_from_eo)\n"
+      << "{\n"
+      << "  v8::Local<v8::ObjectTemplate> instance = constructor->InstanceTemplate();\n"
+      << "  instance->SetInternalFieldCount(1);\n"
+      << "  v8::Handle<v8::ObjectTemplate> prototype = constructor->PrototypeTemplate();\n";
+
+   std::stringstream functions_ss;
+   std::set<std::string> member_names;
+   std::set<std::string> event_member_names;
+   for(auto function : normal_functions)
+     {
+       std::vector<Eolian_Function_Type> function_types;
+       switch (eolian_function_type_get(function))
+         {
+         case EOLIAN_METHOD:
+           function_types = {EOLIAN_METHOD};
+           break;
+         case EOLIAN_PROPERTY:
+           function_types = {EOLIAN_PROP_GET, EOLIAN_PROP_SET};
+           break;
+         case EOLIAN_PROP_GET:
+           function_types = {EOLIAN_PROP_GET};
+           break;
+         case EOLIAN_PROP_SET:
+           function_types = {EOLIAN_PROP_SET};
+           break;
+         default:
+           EINA_CXX_DOM_LOG_ERR(eolian::js::domain) << "Unresolved function type";
+           continue;
+         }
+
+       // generate function registration
+       for (const auto function_type : function_types)
+         {
+           try
+             {
+               std::string member_name;
+               switch (function_type)
+                 {
+                 case EOLIAN_METHOD:
+                   member_name = eolian_function_name_get(function);
+                   break;
+                 case EOLIAN_PROP_SET:
+                   member_name = std::string("set_") + eolian_function_name_get(function);
+                   break;
+                 case EOLIAN_PROP_GET:
+                   member_name = std::string("get_") + eolian_function_name_get(function);
+                   break;
+                 case EOLIAN_PROPERTY:
+                   EINA_CXX_DOM_LOG_ERR(eolian::js::domain) << "EOLIAN_PROPERTY function type is invalid at this point";
+                   return -1;
+                 case EOLIAN_UNRESOLVED:
+                 default:
+                   EINA_CXX_DOM_LOG_ERR(eolian::js::domain) << "Unresolved function type";
+                   return -1;
+                 }
+
+               if(member_names.find(member_name) == member_names.end())
+                 {
+                   member_names.insert(member_name);
+                    std::stringstream ss;
+                    auto output_begin = [&] (std::string name)
+                      {
+                         if(! ::eolian_function_is_constructor(function, klass))
+                           ss << "  prototype->Set( ::efl::eina::js::compatibility_new<v8::String>(isolate, \""
+                              << format::generic(name) << "\")\n"
+                              << "    , ::efl::eina::js::compatibility_new<v8::FunctionTemplate>(isolate, &efl::eo::js::call_function\n"
+                              << "    , efl::eo::js::call_function_data<\n"
+                              << "      ::efl::eina::_mpl::tuple_c<std::size_t";
+                      };
+
+                    output_begin(member_name);
+
+                    const auto key_params = _eolian_function_keys_get(function, function_type);
+                    const auto parameters = _eolian_function_parameters_get(function, function_type);
+
+                    std::vector<const ::Eolian_Function_Parameter*> full_params;
+                    full_params.insert(end(full_params), begin(key_params), end(key_params));
+                    // only one property_get parameter is translated as the function return in C
+                    const auto param_as_return = (EOLIAN_PROP_GET == function_type) && (parameters.size() == 1)
+                      && _function_return_is_missing(function, function_type);
+                    if (!param_as_return)
+                      full_params.insert(end(full_params), begin(parameters), end(parameters));
+
+                    // call_function_data Ins
+                    std::size_t i = 0;
+                    for (auto parameter : full_params)
+                      {
+                        if (EOLIAN_PROP_SET == function_type)
+                          ss << ", " << i;
+                        else
+                          if (EOLIAN_METHOD == function_type)
+                            {
+                               switch (eolian_parameter_direction_get(parameter))
+                                 {
+                                 case EOLIAN_IN_PARAM:
+                                 case EOLIAN_INOUT_PARAM:
+                                   ss << ", " << i;
+                                 default: break;
+                                 }
+                            }
+                        ++i;
+                      }
+
+                    // call_function_data Outs
+                    ss << ">\n      , ::efl::eina::_mpl::tuple_c<std::size_t";
+                    auto key_count = key_params.size();
+                    i = 0;
+                    for (auto parameter : full_params)
+                      {
+                         // ignore keys
+                         if (key_count > 0)
+                           {
+                              --key_count;
+                              ++i;
+                              continue;
+                           }
+                         
+                         // properties doesn't support in/out/inout
+                         if (EOLIAN_PROP_GET == function_type)
+                           ss << ", " << i;
+                         else
+                           if (EOLIAN_METHOD == function_type)
+                             {
+                                switch (eolian_parameter_direction_get(parameter))
+                                  {
+                                  case EOLIAN_OUT_PARAM:
+                                  case EOLIAN_INOUT_PARAM:
+                                    ss << ", " << i;
+                                  default: break;
+                                  }
+                             }
+                         ++i;
+                      }
+
+                    // call_function_data Ownership
+                    ss << ">\n      , std::tuple<\n";
+                    auto sep = "";
+                    for (auto parameter : full_params)
+                      {
+                         auto type = eolian_parameter_type_get(parameter);
+                         if(eolian_type_is_own(type))
+                           ss << sep << "       ::std::true_type";
+                         else
+                           ss << sep << "       ::std::false_type";
+                         sep = ",\n";
+                      }
+                    
+
+                    // call_function_data Return
+                    ss << ">\n      , ";
+
+                    const Eolian_Type *return_type = nullptr;
+                    if (param_as_return)
+                      {
+                         return_type = eolian_parameter_type_get(parameters[0]);
+                      }
+                    else
+                      {
+                         return_type = ::eolian_function_return_type_get(function, function_type);
+                      }
+                    std::string param = "void";
+                    if (nullptr != return_type)
+                      {
+                         param = _eolian_type_cpp_type_named_get(return_type, class_name, need_name_getter);
+                      }
+                    ss << param;
+                    
+
+                    // call_function_data Parameters
+                    ss << "\n      , std::tuple<\n";
+                    sep = "       ";
+                    key_count = key_params.size();
+                    for (auto parameter : full_params)
+                      {
+                         // TODO: REVIEW ALL THIS TOO!!!
+                        auto type = eolian_parameter_type_get(parameter);
+                        auto param = _eolian_type_cpp_type_named_get(type, class_name, need_name_getter);
+
+                        if (!key_count && EOLIAN_PROP_GET == function_type)
+                          param += "*";
+                        else
+                          {
+                             switch(eolian_parameter_direction_get(parameter))
+                               {
+                               case EOLIAN_OUT_PARAM:
+                               case EOLIAN_INOUT_PARAM:
+                                 param += "*";
+                               default: break;
+                               }
+                          }
+                        
+                        ss << sep << param;
+                        sep = ",\n       ";
+                        
+                        if (key_count > 0) --key_count;
+                      }
+                    
+
+                    std::string param_class_names;
+                    for (auto parameter : full_params)
+                      {
+                         param_class_names += '"' + type_class_name(::eolian_parameter_type_get(parameter)) + "\", ";
+                      }
+                    param_class_names += '"' + type_class_name(return_type) + '"';
+
+                    std::string param_class_names_array = "std::array<const char*, ";
+                    param_class_names_array += std::to_string(full_params.size() + 1);
+                    param_class_names_array += ">{{" + param_class_names + "}}";
+
+                    auto output_end = [&] (std::string const& name)
+                      {
+                         ss << "> >(isolate, " << param_class_names_array << ", & ::" << name << ")));\n";
+                      };
+                    switch (function_type)
+                      {
+                 case EOLIAN_METHOD:
+                   output_end(eolian_function_full_c_name_get(function, function_type, EINA_FALSE));
+                   break;
+                      case EOLIAN_PROP_SET:
+                        output_end(eolian_function_full_c_name_get(function, function_type, EINA_FALSE) /*+ std::string("_set")*/);
+                        break;
+                      case EOLIAN_PROP_GET:
+                        output_end(eolian_function_full_c_name_get(function, function_type, EINA_FALSE) /*+ std::string("_get")*/);
+                        break;
+                      case EOLIAN_PROPERTY:
+                        EINA_CXX_DOM_LOG_ERR(eolian::js::domain) << "EOLIAN_PROPERTY function type is invalid at this point";
+                        return -1;
+                      case EOLIAN_UNRESOLVED:
+                      default:
+                        EINA_CXX_DOM_LOG_ERR(eolian::js::domain) << "Unresolved function type";
+                        return -1;
+                      }
+
+                    // Write function to functions stream
+                    functions_ss << ss.str();
+                 }
+             }
+           catch(eolian::js::incomplete_complex_type_error const& e)
+             {
+               EINA_CXX_DOM_LOG_ERR(eolian::js::domain) << "Exception while generating '" << eolian_function_name_get(function) << "': " << e.what();
+             }
+         }
+     }
+
+   // generate all events
+   std::stringstream events_ss;
+   auto generate_events = [&] (Eolian_Class const* klass)
+     {
+       std::stringstream ss;
+       for(efl::eina::iterator< ::Eolian_Event> first ( ::eolian_class_events_get(klass))
+             , last; first != last; ++first)
+         {
+           std::string event_name (::eolian_event_name_get(&*first));
+           std::replace(event_name.begin(), event_name.end(), ',', '_');
+
+           if (!eolian_event_is_beta(&*first) &&
+               event_member_names.find(event_name) == event_member_names.end())
+             {
+                auto tp = eolian_event_type_get(&*first);
+                ss << "  {\n";
+                ss << "    static efl::eo::js::event_information ev_info{&constructor_from_eo, " << eolian_event_c_name_get(&*first);
+                ss << ", &efl::eo::js::event_callback<";
+                ss << (tp ? _eolian_type_cpp_type_named_get(tp, class_name, need_name_getter) : "void");
+                ss << ">, \"" << type_class_name(tp) << "\"};\n";
+                ss << "    " << event_map << "[\"" << event_name << "\"] = &ev_info;\n";
+                ss << "  }\n";
+                event_member_names.insert(event_name);
+             }
+         }
+         events_ss << ss.str();
+     };
+   generate_events(klass);
+   recurse_inherits(klass, generate_events);
+
+   std::stringstream register_from_constructor_end_ss;
+   register_from_constructor_end_ss
+      << "  prototype->Set(::efl::eina::js::compatibility_new<v8::String>(isolate, \"on\")\n"
+      << "    , ::efl::eina::js::compatibility_new<v8::FunctionTemplate>(isolate, &efl::eo::js::on_event\n"
+      << "      , ::efl::eina::js::compatibility_new<v8::External>(isolate, &" << event_map << ")));\n"
+      << "  static_cast<void>(prototype); /* avoid warnings */\n"
+      << "  static_cast<void>(isolate); /* avoid warnings */\n"
+      << "  static_cast<void>(constructor_from_eo); /* avoid warnings */\n"
+      << "  return instance;\n"
+      << "}\n\n";
+
+   std::stringstream name_getters_ss;
+   for (auto const& k : need_name_getter)
+     {
+        name_getters_ss << "  struct " << _class_name_getter(class_name, k) << " { static char const* class_name() { return \"" << k << "\"; } };\n";
+     }
+
+   os << "namespace {\n";
+   os << name_getters_ss.str();
+   os << "}\n\n";
+
+   os << register_from_constructor_begin_ss.str();
+   os << functions_ss.str();
+   os << register_from_constructor_end_ss.str();
+
+   // generate main entry-point for generation
+   os << "EAPI void register_" << lower_case_class_name
+      << "(v8::Handle<v8::Object> global, v8::Isolate* isolate)\n";
+   os << "{\n";
+   os << "  v8::Handle<v8::FunctionTemplate> constructor = ::efl::eina::js::compatibility_new<v8::FunctionTemplate>\n";
+   os << "    (isolate, efl::eo::js::constructor\n"
+      << "     , efl::eo::js::constructor_data(isolate\n"
+         "         , ";
+
+   EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "before print eo_class";
+
+   print_eo_class(klass, os);
+
+   EINA_CXX_DOM_LOG_WARN(eolian::js::domain) << "print eo_class";
+
+   for(auto function : constructor_functions)
+     {
+       auto ftype = eolian_function_type_get(function);
+       if(ftype == EOLIAN_PROPERTY)
+         ftype = EOLIAN_PROP_SET;
+       os << "\n         , & ::"
+          << eolian_function_full_c_name_get(function, ftype, EINA_FALSE);
+     }
+
+   os  << "));\n";
+
+   os << "  static ::efl::eina::js::global_ref<v8::Function> constructor_from_eo;\n";
+   os << events_ss.str();
+   os << "  register_" << lower_case_class_name << "_from_constructor(isolate, constructor, &constructor_from_eo);\n";
+
+   os << "  constructor->SetClassName( ::efl::eina::js::compatibility_new<v8::String>(isolate, \""
+      << format::generic(class_name)
+      << "\"));\n";
+
+   os << "  auto to_export = ::efl::eo::js::get_namespace({";
+   if (namespace_size(klass))
+     {
+        bool comma = false;
+        for (efl::eina::iterator<const char> ns_it(::eolian_class_namespaces_get(klass)), ns_end; ns_it != ns_end; ++ns_it)
+          {
+             if (comma)
+               os << ", ";
+             comma = true;
+             os << '"' << format::generic(&*ns_it) << '"';
+          }
+     }
+   os << "}, isolate, global);\n";
+
+   os << "  to_export->Set( ::efl::eina::js::compatibility_new<v8::String>(isolate, \""
+      << format::generic(class_name) << "\")"
+      << ", constructor->GetFunction());\n";
+
+
+   os << "  {\n";
+   os << "    v8::Handle<v8::FunctionTemplate> constructor = ::efl::eina::js::compatibility_new<v8::FunctionTemplate>\n";
+   os << "      (isolate, &efl::eo::js::construct_from_eo);\n";
+   os << "    constructor->SetClassName( ::efl::eina::js::compatibility_new<v8::String>(isolate, \""
+      << format::generic(class_name)
+      << "\"));\n";
+   os << "    v8::Local<v8::ObjectTemplate> instance = "
+      << "register_" << lower_case_class_name << "_from_constructor(isolate, constructor, &constructor_from_eo);\n";
+   os << "    ::efl::eina::js::make_persistent(isolate, instance);\n";
+   os << "    constructor_from_eo = {isolate, constructor->GetFunction()};\n";
+   os << "    ::efl::eina::js::register_class_constructor(\"" << class_full_name << "\", constructor_from_eo.handle());\n";
+   os << "  }\n";
+
+   os << structs_ss.str();
+
+   // generate enumerations
+   for (efl::eina::iterator<Eolian_Type> first(::eolian_type_enums_get_by_file(file_basename.c_str()))
+        , last; first != last; ++first)
+     {
+        auto tp = &*first;
+        if (::eolian_type_is_extern(tp))
+          continue;
+        std::string enum_name = ::eolian_type_name_get(tp);
+        os << "  {\n";
+        os << "    auto to_export = ::efl::eo::js::get_namespace({";
+        bool comma = false;
+        for (efl::eina::iterator<const char> ns_it(::eolian_type_namespaces_get(tp)), ns_end; ns_it != ns_end; ++ns_it)
+          {
+            if (comma)
+              os << ", ";
+            comma = true;
+            os << '"' << format::generic(&*ns_it) << '"';
+          }
+        os << "}, isolate, global);\n";
+        os << "    v8::Handle<v8::Object> enum_obj = efl::eina::js::compatibility_new<v8::Object>(isolate);\n";
+        os << "    to_export->Set(efl::eina::js::compatibility_new<v8::String>(isolate, \""
+           << format::generic(enum_name) << "\"), enum_obj);\n";
+        for (efl::eina::iterator<Eolian_Enum_Type_Field> ef(::eolian_type_enum_fields_get(tp))
+             , ef_end; ef != ef_end; ++ef)
+          {
+             auto field_name = ::eolian_type_enum_field_name_get(&*ef);
+             auto field_c_name = ::eolian_type_enum_field_c_name_get(&*ef);
+             if (!field_name || !field_c_name)
+               {
+                  EINA_CXX_DOM_LOG_ERR(eolian::js::domain) << "Could not get enum field name";
+                  continue;
+               }
+             os << "    enum_obj->Set(efl::eina::js::compatibility_new<v8::String>(isolate, \"" << format::constant(field_name) << "\"),\n";
+             os << "                  efl::eina::js::compatibility_new<v8::Int32>(isolate, static_cast<int32_t>(::" << field_c_name << ")));\n";
+          }
+        os << "  }\n";
+     }
+
+   os << "}\n\n";
+
+   for(std::size_t i = 0, j = namespace_size(klass); i != j; ++i)
+     os << "}";
+   os << "\n";
+
+
+}
index d12b0c9..8f54628 100644 (file)
@@ -22,6 +22,7 @@
 #include <eina_log.hh>
 #include <eina_optional.hh>
 #include <eina_integer_sequence.hh>
+#include <eina_pp.hh>
 
 /**
  * @page eina_cxx_main Eina C++ (BETA)
index b867f14..d084918 100644 (file)
@@ -114,7 +114,10 @@ struct accessor_common_base
    * @warning It is important to take care when using it, since the
    * handle will be automatically release upon object destruction.
    */
-  Eina_Accessor* native_handle() const;
+  Eina_Accessor* native_handle() const
+  {
+    return _impl;
+  }
 
   /**
    * @brief Swap content between both objects.
index eb9e557..d352de5 100644 (file)
@@ -32,6 +32,8 @@ public:
   typedef typename _base_type::reverse_iterator reverse_iterator; /**< Type for reverse iterator for this container. */
   typedef typename _base_type::const_reverse_iterator const_reverse_iterator; /**< Type for reverse iterator for this container. */
 
+  typedef typename _base_type::native_handle_type native_handle_type;
+
   using _base_type::_base_type;
   using _base_type::clear;
   using _base_type::size;
@@ -59,6 +61,7 @@ public:
   using _base_type::ciend;
   using _base_type::swap;
   using _base_type::max_size;
+  using _base_type::release_native_handle;
   using _base_type::native_handle;
 
   friend bool operator==(array<T, CloneAllocator> const& lhs, array<T, CloneAllocator> const& rhs)
@@ -131,6 +134,101 @@ struct _ptr_eo_array_iterator : _ptr_array_iterator<Eo>
   using _base_type::native_handle;
 };
 
+/**
+ * @internal
+ */
+struct _eo_array_access_traits : _ptr_array_access_traits
+{
+  template <typename T>
+  struct iterator
+  {
+    typedef _ptr_eo_array_iterator<T> type;
+  };
+  template <typename T>
+  struct const_iterator : iterator<T const> {};
+
+  template <typename T>
+  static T& back(Eina_Array* array)
+  {
+    return *static_cast<T*>(static_cast<void*>(array->data[size<T>(array)-1]));
+  }
+  template <typename T>
+  static T const& back(Eina_Array const* array)
+  {
+    return _eo_array_access_traits::back<T>(const_cast<Eina_Array*>(array));
+  }
+  template <typename T>
+  static T& front(Eina_Array* array)
+  {
+    return *static_cast<T*>(static_cast<void*>(array->data[0]));
+  }
+  template <typename T>
+  static T const& front(Eina_Array const* array)
+  {
+    return _eo_array_access_traits::front<T>(const_cast<Eina_Array*>(array));
+  }
+  template <typename T>
+  static typename iterator<T>::type begin(Eina_Array* array)
+  {
+    return _ptr_eo_array_iterator<T>(array->data);
+  }
+  template <typename T>
+  static typename iterator<T>::type end(Eina_Array* array)
+  {
+    return _ptr_eo_array_iterator<T>(array->data + size<T>(array));
+  }
+  template <typename T>
+  static typename const_iterator<T>::type begin(Eina_Array const* array)
+  {
+    return _eo_array_access_traits::begin<T>(const_cast<Eina_Array*>(array));
+  }
+  template <typename T>
+  static typename const_iterator<T>::type end(Eina_Array const* array)
+  {
+    return _eo_array_access_traits::end<T>(const_cast<Eina_Array*>(array));
+  }
+  template <typename T>
+  static std::reverse_iterator<typename iterator<T>::type> rbegin(Eina_Array* array)
+  {
+    return std::reverse_iterator<_ptr_eo_array_iterator<T> >(_eo_array_access_traits::end<T>(array));
+  }
+  template <typename T>
+  static std::reverse_iterator<typename iterator<T>::type> rend(Eina_Array* array)
+  {
+    return std::reverse_iterator<_ptr_eo_array_iterator<T> >(_eo_array_access_traits::begin<T>(array));
+  }
+  template <typename T>
+  static std::reverse_iterator<typename const_iterator<T>::type> rbegin(Eina_Array const* array)
+  {
+    return std::reverse_iterator<_ptr_eo_array_iterator<T>const>(_eo_array_access_traits::end<T>(array));
+  }
+  template <typename T>
+  static std::reverse_iterator<typename const_iterator<T>::type> rend(Eina_Array const* array)
+  {
+    return std::reverse_iterator<_ptr_eo_array_iterator<T>const>(_eo_array_access_traits::begin<T>(array));
+  }
+  template <typename T>
+  static typename const_iterator<T>::type cbegin(Eina_Array const* array)
+  {
+    return _eo_array_access_traits::begin<T>(array);
+  }
+  template <typename T>
+  static typename const_iterator<T>::type cend(Eina_Array const* array)
+  {
+    return _eo_array_access_traits::end<T>(array);
+  }
+  template <typename T>
+  static std::reverse_iterator<typename const_iterator<T>::type> crbegin(Eina_Array const* array)
+  {
+    return _eo_array_access_traits::rbegin<T>(array);
+  }
+  template <typename T>
+  static std::reverse_iterator<typename const_iterator<T>::type> crend(Eina_Array const* array)
+  {
+    return _eo_array_access_traits::rend<T>(array);
+  }
+};
+    
 template <typename T, typename CloneAllocator>
 class array<T, CloneAllocator, typename std::enable_if<std::is_base_of<::efl::eo::concrete, T>::value>::type>
   : ptr_array<Eo, typename std::conditional
@@ -156,7 +254,9 @@ public:
   typedef std::reverse_iterator<iterator> reverse_iterator; /**< Type for reverse iterator for this container. */
   typedef std::reverse_iterator<const_iterator> const_reverse_iterator; /**< Type for reverse iterator for this container. */
 
-  explicit array(Eina_Array* handle)
+  typedef typename _base_type::native_handle_type native_handle_type; /**< Type for the native handle of the container. */
+
+  explicit array(native_handle_type handle)
     : _base_type(handle) {}
   array(clone_allocator_type alloc) : _base_type(alloc) {}
   array() {}
@@ -318,6 +418,7 @@ public:
   
   using _base_type::swap;
   using _base_type::max_size;
+  using _base_type::release_native_handle;
   using _base_type::native_handle;
 
   friend bool operator==(array<T, CloneAllocator> const& lhs, array<T, CloneAllocator> const& rhs)
@@ -331,7 +432,154 @@ bool operator!=(array<T, CloneAllocator> const& lhs, array<T, CloneAllocator> co
 {
   return !(lhs == rhs);
 }
+
+template <typename T, typename Enable = void>
+class range_array : range_ptr_array<T>
+{
+  typedef range_ptr_array<T> _base_type;
+public:
+  typedef typename _base_type::value_type value_type;
+  typedef typename _base_type::reference reference;
+  typedef typename _base_type::const_reference const_reference;
+  typedef typename _base_type::const_iterator const_iterator;
+  typedef typename _base_type::iterator iterator;
+  typedef typename _base_type::pointer pointer;
+  typedef typename _base_type::const_pointer const_pointer;
+  typedef typename _base_type::size_type size_type;
+  typedef typename _base_type::difference_type difference_type;
+
+  typedef typename _base_type::reverse_iterator reverse_iterator;
+  typedef typename _base_type::const_reverse_iterator const_reverse_iterator;
+
+  typedef typename _base_type::native_handle_type native_handle_type;
+
+  range_array& operator=(range_array&& other) = default;
+
+  using _base_type::_base_type;
+  using _base_type::size;
+  using _base_type::empty;
+  using _base_type::back;
+  using _base_type::front;
+  using _base_type::begin;
+  using _base_type::end;
+  using _base_type::rbegin;
+  using _base_type::rend;
+  using _base_type::cbegin;
+  using _base_type::cend;
+  using _base_type::crbegin;
+  using _base_type::crend;
+  using _base_type::release_native_handle;
+  using _base_type::native_handle;
+};
+
+template <typename T>
+class range_array<T, typename std::enable_if<std::is_base_of<::efl::eo::concrete, T>::value>::type>
+  : range_ptr_array<Eo>
+{
+  typedef range_ptr_array<Eo> _base_type;
+  typedef range_array<T> _self_type;
+public:
+  typedef T value_type;
+  typedef value_type& reference;
+  typedef value_type const& const_reference;
+  typedef _ptr_eo_array_iterator<value_type const> const_iterator;
+  typedef _ptr_eo_array_iterator<value_type> iterator;
+  typedef value_type* pointer;
+  typedef value_type const* const_pointer;
+  typedef std::size_t size_type;
+  typedef std::ptrdiff_t difference_type;
+
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+  typedef typename _base_type::native_handle_type native_handle_type;
+
+  explicit range_array(native_handle_type handle)
+    : _base_type(handle) {}
+  range_array() {}
+  range_array(range_array<T> const& other)
+    : _base_type(other.native_handle())
+  {
+  }
+  range_array<T>& operator=(range_array<T>const& other)
+  {
+    _base_type::_handle = other._handle;
+    return *this;
+  }
+  range_array& operator=(range_array&& other) = default;
+  range_array(range_array&& other) = default;
   
+  using _base_type::size;
+  using _base_type::empty;
+
+  reference front()
+  {
+    return _eo_array_access_traits::front<value_type>(native_handle());
+  }
+  reference back()
+  {
+    return _eo_array_access_traits::back<value_type>(native_handle());
+  }
+  const_reference front() const { return const_cast<_self_type*>(this)->front(); }
+  const_reference back() const { return const_cast<_self_type*>(this)->back(); }
+  iterator begin()
+  {
+    return _eo_array_access_traits::begin<value_type>(native_handle());
+  }
+  iterator end()
+  {
+    return _eo_array_access_traits::end<value_type>(native_handle());
+  }
+  const_iterator begin() const
+  {
+    return const_cast<_self_type*>(this)->begin();
+  }
+  const_iterator end() const
+  {
+    return const_cast<_self_type*>(this)->end();
+  }
+  const_iterator cbegin() const
+  {
+    return begin();
+  }
+  const_iterator cend() const
+  {
+    return end();
+  }
+  reverse_iterator rbegin()
+  {
+    return _eo_array_access_traits::rbegin<value_type>(native_handle());
+  }
+  reverse_iterator rend()
+  {
+    return _eo_array_access_traits::rend<value_type>(native_handle());
+  }
+  const_reverse_iterator rbegin() const
+  {
+    return const_cast<_self_type*>(this)->rbegin();
+  }
+  const_reverse_iterator rend() const
+  {
+    return const_cast<_self_type*>(this)->rend();
+  }
+  const_reverse_iterator crbegin() const
+  {
+    return rbegin();
+  }
+  const_reverse_iterator crend() const
+  {
+    return rend();
+  }
+  using _base_type::swap;
+  using _base_type::release_native_handle;
+  using _base_type::native_handle;
+
+  friend bool operator==(range_array<T> const& rhs, range_array<T> const& lhs)
+  {
+    return rhs.size() == lhs.size() && std::equal(rhs.begin(), rhs.end(), lhs.begin());
+  }
+};
+    
 } }
 
 #endif
index 824d6d6..76ff620 100644 (file)
@@ -154,7 +154,8 @@ struct malloc_clone_allocator
   template <typename T>
   static void deallocate_clone(T const* p)
   {
-    static_assert(std::is_pod<T>::value, "malloc_clone_allocator can only be used with POD types");
+    static_assert(std::is_pod<T>::value || std::is_void<T>::value
+                  , "malloc_clone_allocator can only be used with POD types");
     std::free(const_cast<T*>(p));
   }
 };
diff --git a/src/bindings/eina_cxx/eina_function.hh b/src/bindings/eina_cxx/eina_function.hh
new file mode 100644 (file)
index 0000000..cef6da5
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef EFL_EINA_FUNCTION_HH
+#define EFL_EINA_FUNCTION_HH
+
+namespace efl { namespace eina { namespace _mpl {
+
+template <typename T>
+struct function_params;
+
+template <typename R, typename... P>
+struct function_params<R(*)(P...)>
+{
+  typedef std::tuple<P...> type;
+};
+
+template <typename T>
+struct function_return;
+
+template <typename R, typename... P>
+struct function_return<R(*)(P...)>
+{
+  typedef R type;
+};
+      
+} } }
+
+#endif
index 854bb8f..f99c871 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef EINA_CXX_EINA_INTEGER_SEQUENCE_HH
 #define EINA_CXX_EINA_INTEGER_SEQUENCE_HH
 
+#include <cstdlib>
+
 /**
  * @addtogroup Eina_Cxx_Data_Types_Group
  *
index 760ada3..1221867 100644 (file)
@@ -190,6 +190,8 @@ public:
   typedef typename _base_type::reverse_iterator reverse_iterator;
   typedef typename _base_type::const_reverse_iterator const_reverse_iterator;
 
+  using _base_type::native_handle_type;
+  
   list& operator=(list&& other) = default;
   list(list&& other) = default;
   list() = default;
@@ -224,6 +226,7 @@ public:
   using _base_type::max_size;
   using _base_type::native_handle;
   using _base_type::accessor;
+  using _base_type::release_native_handle;
 };
 
 template <typename T, typename CloneAllocator>
@@ -251,7 +254,9 @@ public:
   typedef std::reverse_iterator<iterator> reverse_iterator;
   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
 
-  explicit list(Eina_List* handle)
+  using _base_type::native_handle_type;
+
+  explicit list(typename _self_type::native_handle_type handle)
     : _base_type(handle) {}
   list(clone_allocator_type alloc) : _base_type(alloc) {}
   list() {}
@@ -295,6 +300,7 @@ public:
   using _base_type::get_clone_allocator;
   using _base_type::pop_back;
   using _base_type::pop_front;
+  using _base_type::release_native_handle;
 
   void push_back(const_reference w)
   {
@@ -464,6 +470,8 @@ public:
   typedef typename _base_type::reverse_iterator reverse_iterator;
   typedef typename _base_type::const_reverse_iterator const_reverse_iterator;
 
+  using _base_type::native_handle_type;
+
   using _base_type::_base_type;
   using _base_type::size;
   using _base_type::empty;
@@ -501,9 +509,9 @@ public:
   typedef std::reverse_iterator<iterator> reverse_iterator;
   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
 
-  typedef typename _base_type::native_handle_type native_handle_type;
+  using _base_type::native_handle_type;
 
-  explicit range_list(native_handle_type handle)
+  explicit range_list(typename _self_type::native_handle_type handle)
     : _base_type(handle) {}
   range_list() {}
   range_list(range_list<T> const& other)
diff --git a/src/bindings/eina_cxx/eina_logical.hh b/src/bindings/eina_cxx/eina_logical.hh
new file mode 100644 (file)
index 0000000..d53d354
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef EFL_EINA_LOGICAL_HH
+#define EFL_EINA_LOGICAL_HH
+
+#include <type_traits>
+
+namespace efl { namespace eina { namespace _mpl {
+
+template <bool... N>
+struct or_;
+
+template <>
+struct or_<> : std::integral_constant<bool, false> {};
+
+template <bool B>
+struct or_<B> : std::integral_constant<bool, B> {};
+
+template <bool B1, bool B2, bool... Bs>
+struct or_<B1, B2, Bs...> : std::integral_constant<bool, B1 || B2 || or_<Bs...>::value> {};
+
+template <bool... N>
+struct and_;
+
+template <>
+struct and_<> : std::integral_constant<bool, true> {};
+
+template <bool B>
+struct and_<B> : std::integral_constant<bool, B> {};
+
+template <bool B1, bool B2, bool... Bs>
+struct and_<B1, B2, Bs...> : std::integral_constant<bool, B1 && B2 && and_<Bs...>::value> {};
+
+} } }
+
+#endif
diff --git a/src/bindings/eina_cxx/eina_pp.hh b/src/bindings/eina_cxx/eina_pp.hh
new file mode 100644 (file)
index 0000000..22a6a22
--- /dev/null
@@ -0,0 +1,8 @@
+
+#ifndef EINA_PP_HH
+#define EINA_PP_HH
+
+#define EINA_STRINGIZE_IMPL(x) #x
+#define EINA_STRINGIZE(x) EINA_STRINGIZE_IMPL(x)
+
+#endif
index 2f40627..f47202e 100644 (file)
@@ -295,10 +295,12 @@ struct range_ptr_array : _range_template<T, _ptr_array_access_traits>
   typedef _range_template<T, _ptr_array_access_traits> _base_type;  /**< Type for the base class. */
   typedef typename _base_type::value_type value_type;  /**< The type of each element. */
 
+  typedef typename _base_type::native_handle_type native_handle_type;
+
   /**
    * @brief Creates a range from a native Eina array handle.
    */
-  range_ptr_array(Eina_Array* array)
+  range_ptr_array(native_handle_type array)
     : _base_type(array)
   {}
 
@@ -391,7 +393,7 @@ struct _ptr_array_common_base
   /**
    * @internal
    */
-  T* _new_clone(T const& a)
+  T* _new_clone(typename container_value_type<T>::type const& a)
   {
     return _get_clone_allocator().allocate_clone(a);
   }
@@ -402,6 +404,7 @@ struct _ptr_array_common_base
   struct _ptr_array_impl : CloneAllocator
   {
     _ptr_array_impl() : _array( ::eina_array_new(32u) ) {}
+    _ptr_array_impl(Eina_Array* array) : _array(array) {}
     _ptr_array_impl(CloneAllocator allocator)
       : clone_allocator_type(allocator), _array( ::eina_array_new(32u)) {}
 
@@ -449,6 +452,8 @@ public:
 
   typedef std::unique_ptr<value_type, clone_allocator_deleter<clone_allocator_type> > _unique_ptr;
 
+  typedef Eina_Array* native_handle_type;
+
   /**
    * @brief Default constructor. Create an empty array.
    *
@@ -1210,6 +1215,13 @@ public:
    */
   size_type max_size() const { return -1; }
 
+  Eina_Array* release_native_handle()
+  {
+    Eina_Array* tmp = this->_impl._array;
+    this->_impl._array = ::eina_array_new(32u);
+    return tmp;
+  }
+  
   /**
    * @brief Get a handle for the wrapped Eina_Array.
    * @return Handle for the native Eina array.
index 2f18d10..f7254b1 100644 (file)
@@ -9,6 +9,7 @@
 #include <eina_eo_concrete_fwd.hh>
 #include <eina_iterator.hh>
 #include <eina_throw.hh>
+#include <eina_range_types.hh>
 
 #include <memory>
 #include <iterator>
@@ -370,7 +371,7 @@ struct _ptr_list_common_base
   /**
    * @internal
    */
-  T* _new_clone(T const& a)
+  T* _new_clone(typename container_value_type<T>::type const& a)
   {
     return _get_clone_allocator().allocate_clone(a);
   }
@@ -413,11 +414,12 @@ class ptr_list : protected _ptr_list_common_base<T, CloneAllocator>
 {
   typedef _ptr_list_common_base<T, CloneAllocator> _base_type; /**< Type for the base class. */
 public:
-  typedef T value_type; /**< The type of each element. */
-  typedef T& reference; /**< Type for a reference to an element. */
-  typedef T const& const_reference; /**< Type for a constant reference to an element. */
-  typedef _ptr_list_iterator<T const> const_iterator; /**< Type for a iterator for this container. */
-  typedef _ptr_list_iterator<T> iterator; /**< Type for a constant iterator for this container. */
+  typedef typename container_value_type<T>::type
+    value_type; /**< The type of each element. */
+  typedef value_type& reference; /**< Type for a reference to an element. */
+  typedef value_type const& const_reference; /**< Type for a constant reference to an element. */
+  typedef _ptr_list_iterator<value_type const> const_iterator; /**< Type for a iterator for this container. */
+  typedef _ptr_list_iterator<value_type> iterator; /**< Type for a constant iterator for this container. */
   typedef T* pointer; /**< Type for a pointer to an element. */
   typedef T const* const_pointer; /**< Type for a constant pointer for an element. */
   typedef std::size_t size_type; /**< Type for size information. */
@@ -427,6 +429,8 @@ public:
   typedef std::reverse_iterator<iterator> reverse_iterator; /**< Type for reverse iterator for this container. */
   typedef std::reverse_iterator<const_iterator> const_reverse_iterator; /**< Type for reverse iterator for this container. */
 
+  typedef Eina_List* native_handle_type;
+  
   typedef std::unique_ptr<value_type, clone_allocator_deleter<clone_allocator_type> > _unique_ptr;
 
   /**
@@ -554,7 +558,7 @@ public:
    */
   std::size_t size() const
   {
-    return _ptr_list_access_traits::size<T>(this->_impl._list);
+    return _ptr_list_access_traits::size<value_type>(this->_impl._list);
   }
 
   /**
@@ -566,7 +570,7 @@ public:
    */
   bool empty() const
   {
-    return _ptr_list_access_traits::empty<T>(this->_impl._list);
+    return _ptr_list_access_traits::empty<value_type>(this->_impl._list);
   }
 
   /**
@@ -940,7 +944,7 @@ public:
    */
   value_type& back()
   {
-    return _ptr_list_access_traits::back<T>(this->_impl._list);
+    return _ptr_list_access_traits::back<value_type>(this->_impl._list);
   }
 
   /**
@@ -952,7 +956,7 @@ public:
    */
   value_type const& back() const
   {
-    return _ptr_list_access_traits::back<T>(this->_impl._list);
+    return _ptr_list_access_traits::back<value_type>(this->_impl._list);
   }
 
   /**
@@ -961,7 +965,7 @@ public:
    */
   value_type& front()
   {
-    return _ptr_list_access_traits::front<T>(this->_impl._list);
+    return _ptr_list_access_traits::front<value_type>(this->_impl._list);
   }
 
   /**
@@ -973,7 +977,7 @@ public:
    */
   value_type const& front() const
   {
-    return _ptr_list_access_traits::front<T>(this->_impl._list);
+    return _ptr_list_access_traits::front<value_type>(this->_impl._list);
   }
 
   /**
@@ -985,7 +989,7 @@ public:
    */
   const_iterator begin() const
   {
-    return _ptr_list_access_traits::cbegin<T>(this->_impl._list);
+    return _ptr_list_access_traits::cbegin<value_type>(this->_impl._list);
   }
 
   /**
@@ -997,7 +1001,7 @@ public:
    */
   const_iterator end() const
   {
-    return _ptr_list_access_traits::cend<T>(this->_impl._list);
+    return _ptr_list_access_traits::cend<value_type>(this->_impl._list);
   }
 
   /**
@@ -1010,7 +1014,7 @@ public:
    */
   iterator begin()
   {
-    return _ptr_list_access_traits::begin<T>(this->_impl._list);
+    return _ptr_list_access_traits::begin<value_type>(this->_impl._list);
   }
 
   /**
@@ -1026,7 +1030,7 @@ public:
    */
   iterator end()
   {
-    return _ptr_list_access_traits::end<T>(this->_impl._list);
+    return _ptr_list_access_traits::end<value_type>(this->_impl._list);
   }
 
   /**
@@ -1038,7 +1042,7 @@ public:
    */
   const_reverse_iterator rbegin() const
   {
-    return _ptr_list_access_traits::rbegin<T>(this->_impl._list);
+    return _ptr_list_access_traits::rbegin<value_type>(this->_impl._list);
   }
 
   /**
@@ -1050,7 +1054,7 @@ public:
    */
   const_reverse_iterator rend() const
   {
-    return _ptr_list_access_traits::rend<T>(this->_impl._list);
+    return _ptr_list_access_traits::rend<value_type>(this->_impl._list);
   }
 
   /**
@@ -1063,7 +1067,7 @@ public:
    */
   reverse_iterator rbegin()
   {
-    return _ptr_list_access_traits::rbegin<T>(this->_impl._list);
+    return _ptr_list_access_traits::rbegin<value_type>(this->_impl._list);
   }
 
   /**
@@ -1080,7 +1084,7 @@ public:
    */
   reverse_iterator rend()
   {
-    return _ptr_list_access_traits::rend<T>(this->_impl._list);
+    return _ptr_list_access_traits::rend<value_type>(this->_impl._list);
   }
 
   /**
@@ -1093,7 +1097,7 @@ public:
    */
   const_iterator cbegin() const
   {
-    return _ptr_list_access_traits::cbegin<T>(this->_impl._list);
+    return _ptr_list_access_traits::cbegin<value_type>(this->_impl._list);
   }
 
   /**
@@ -1106,7 +1110,7 @@ public:
    */
   const_iterator cend() const
   {
-    return _ptr_list_access_traits::cend<T>(this->_impl._list);
+    return _ptr_list_access_traits::cend<value_type>(this->_impl._list);
   }
 
   /**
@@ -1119,7 +1123,7 @@ public:
    */
   const_reverse_iterator crbegin() const
   {
-    return _ptr_list_access_traits::crbegin<T>(this->_impl._list);
+    return _ptr_list_access_traits::crbegin<value_type>(this->_impl._list);
   }
 
   /**
@@ -1132,7 +1136,7 @@ public:
    */
   const_reverse_iterator crend() const
   {
-    return _ptr_list_access_traits::crend<T>(this->_impl._list);
+    return _ptr_list_access_traits::crend<value_type>(this->_impl._list);
   }
 
   /**
@@ -1143,9 +1147,9 @@ public:
    * the first element of the list. If the list is empty the returned
    * iterator is the same as the one returned by @ref iend().
    */
-  eina::iterator<T> ibegin()
+  eina::iterator<value_type> ibegin()
   {
-    return _ptr_list_access_traits::ibegin<T>(this->_impl._list);
+    return _ptr_list_access_traits::ibegin<value_type>(this->_impl._list);
   }
 
   /**
@@ -1160,9 +1164,9 @@ public:
    * @note Note that attempting to access this position causes undefined
    * behavior.
    */
-  eina::iterator<T> iend()
+  eina::iterator<value_type> iend()
   {
-    return _ptr_list_access_traits::iend<T>(this->_impl._list);
+    return _ptr_list_access_traits::iend<value_type>(this->_impl._list);
   }
 
   /**
@@ -1174,7 +1178,7 @@ public:
    */
   eina::iterator<T const> ibegin() const
   {
-    return _ptr_list_access_traits::ibegin<T>(this->_impl._list);
+    return _ptr_list_access_traits::ibegin<value_type>(this->_impl._list);
   }
 
   /**
@@ -1186,7 +1190,7 @@ public:
    */
   eina::iterator<T const> iend() const
   {
-    return _ptr_list_access_traits::iend<T>(this->_impl._list);
+    return _ptr_list_access_traits::iend<value_type>(this->_impl._list);
   }
 
   /**
@@ -1199,7 +1203,7 @@ public:
    */
   eina::iterator<T const> cibegin() const
   {
-    return _ptr_list_access_traits::cibegin<T>(this->_impl._list);
+    return _ptr_list_access_traits::cibegin<value_type>(this->_impl._list);
   }
 
   /**
@@ -1212,7 +1216,7 @@ public:
    */
   eina::iterator<T const> ciend() const
   {
-    return _ptr_list_access_traits::ciend<T>(this->_impl._list);
+    return _ptr_list_access_traits::ciend<value_type>(this->_impl._list);
   }
 
   /**
@@ -1230,6 +1234,13 @@ public:
    */
   size_type max_size() const { return -1; }
 
+  Eina_List* release_native_handle()
+  {
+    Eina_List* tmp = this->_impl._list;
+    this->_impl._list = 0;
+    return tmp;
+  }
+  
   /**
    * @brief Get a handle for the wrapped @c Eina_List.
    * @return Handle for the native Eina list.
@@ -1275,9 +1286,9 @@ public:
    * @brief Get a @ref eina::accessor for the list.
    * @return <tt>eina::accessor</tt> to the list.
    */
-  eina::accessor<T> accessor()
+  eina::accessor<value_type> accessor()
   {
-    return eina::accessor<T>(eina_list_accessor_new(this->_impl._list));
+    return eina::accessor<value_type>(eina_list_accessor_new(this->_impl._list));
   }
 };
 
index 844e2ef..313ca05 100644 (file)
@@ -22,11 +22,12 @@ namespace efl { namespace eina {
 template <typename T, typename Traits>
 struct _const_range_template
 {
-  typedef typename Traits::template const_iterator<T>::type const_iterator; /**< Type for constant iterator to the range. */
-  typedef typename Traits::template iterator<T>::type iterator; /**< Type for iterator to the range. */
-  typedef T value_type; /**< The type of each element. */
-  typedef T& reference; /**< Type for a reference to an element. */
-  typedef T const& const_reference; /**< Type for a constant reference to an element. */
+  typedef typename container_value_type<T>::type
+    value_type; /**< The type of each element. */
+  typedef typename Traits::template const_iterator<value_type>::type const_iterator; /**< Type for constant iterator to the range. */
+  typedef typename Traits::template iterator<value_type>::type iterator; /**< Type for iterator to the range. */
+  typedef value_type& reference; /**< Type for a reference to an element. */
+  typedef value_type const& const_reference; /**< Type for a constant reference to an element. */
   typedef T* pointer; /**< Type for a pointer to an element. */
   typedef T const* const_pointer; /**< Type for a constant pointer to an element. */
   typedef std::reverse_iterator<iterator> reverse_iterator; /**< Type for reverse iterator to the range. */
@@ -50,6 +51,17 @@ struct _const_range_template
     : _handle(handle) {}
 
   /**
+   * @brief Release the handle of the native Eina container.
+   * @return Handle for the native Eina container.
+   */
+  native_handle_type release_native_handle()
+  {
+    auto h = _handle;
+    _handle = nullptr;
+    return h;
+  }
+
+  /**
    * @brief Get a constant handle for the native Eina container.
    * @return Constant handle for the native Eina container.
    */
@@ -241,10 +253,13 @@ void swap(_const_range_template<T, Traits>& lhs, _const_range_template<T, Traits
 template <typename T, typename Traits>
 struct _mutable_range_template : _const_range_template<T, Traits>
 {
-  typedef T value_type; /**< The type of each element. */
-  typedef typename Traits::template iterator<T>::type iterator; /**< Type for a iterator to the range. */
+  typedef typename container_value_type<T>::type
+    value_type; /**< The type of each element. */
+  typedef value_type& reference_type;
+  typedef value_type const& const_reference_type;
+  typedef typename Traits::template iterator<value_type>::type iterator; /**< Type for a iterator to the range. */
   typedef std::reverse_iterator<iterator> reverse_iterator; /**< Type for constant reverse iterator to the range. */
-  typedef typename Traits::template native_handle<T>::type native_handle_type; /**< Type for the native handle of the container. */
+  typedef typename Traits::template native_handle<value_type>::type native_handle_type; /**< Type for the native handle of the container. */
   typedef _const_range_template<T, Traits> _base_type;  /**< Type for the base class. */
 
   /**
@@ -254,6 +269,17 @@ struct _mutable_range_template : _const_range_template<T, Traits>
     : _base_type(handle) {}
 
   /**
+   * @brief Release the handle of the native Eina container.
+   * @return Handle for the native Eina container.
+   */
+  native_handle_type release_native_handle()
+  {
+    auto h = _handle;
+    _handle = nullptr;
+    return h;
+  }
+
+  /**
    * @brief Get a constant handle for the native Eina container.
    * @return Constant handle for the native Eina container.
    */
@@ -266,7 +292,7 @@ struct _mutable_range_template : _const_range_template<T, Traits>
    * @brief Get a reference to the last element.
    * @return Reference to the last element of the range.
    */
-  value_type& back() const
+  reference_type back() const
   {
     return Traits::template back<value_type>(native_handle());
   }
@@ -275,7 +301,7 @@ struct _mutable_range_template : _const_range_template<T, Traits>
    * @brief Get a reference to the first element.
    * @return Reference to the first element of the range.
    */
-  value_type& front() const
+  reference_type front() const
   {
     return Traits::template front<value_type>(native_handle());
   }
@@ -355,11 +381,12 @@ protected:
 template <typename T, typename Traits>
 struct _range_template : private std::conditional
   <std::is_const<T>::value
-   , _const_range_template<typename std::remove_const<T>::type, Traits>
-   , _mutable_range_template<T, Traits> >::type
+   , _const_range_template<typename nonconst_container_value_type<T>::type, Traits>
+   , _mutable_range_template<typename nonconst_container_value_type<T>::type, Traits>
+  >::type
 {
   typedef std::integral_constant<bool, !std::is_const<T>::value> is_mutable; /**< Type that specifies if the elements can be modified. */
-  typedef typename std::remove_const<T>::type value_type; /**< The type of each element. */
+  typedef typename nonconst_container_value_type<T>::type value_type; /**< The type of each element. */
   typedef typename std::conditional<is_mutable::value, _mutable_range_template<value_type, Traits>
                                     , _const_range_template<value_type, Traits> >::type _base_type; /**< Type for the base class. */
   typedef typename _base_type::native_handle_type native_handle_type; /**< Type for the native handle of the container. */
@@ -368,9 +395,9 @@ struct _range_template : private std::conditional
   typedef value_type const& const_reference; /**< Type for a constant reference to an element. */
   typedef value_type* pointer; /**< Type for a pointer to an element. */
   typedef value_type const* const_pointer; /**< Type for a constant pointer to an element. */
-  typedef typename Traits::template const_iterator<T>::type const_iterator; /**< Type for constant iterator to the range. */
+  typedef typename Traits::template const_iterator<value_type>::type const_iterator; /**< Type for constant iterator to the range. */
   typedef typename _base_type::const_reverse_iterator const_reverse_iterator; /**< Type for constant reverse iterator to the range. */
-  typedef typename Traits::template iterator<T>::type iterator; /**< Type for iterator to the range. */
+  typedef typename Traits::template iterator<value_type>::type iterator; /**< Type for iterator to the range. */
   typedef typename _base_type::reverse_iterator reverse_iterator; /**< Type for reverse iterator to the range. */
   typedef typename _base_type::size_type size_type; /**< Type for size information. */
   typedef typename _base_type::difference_type difference_type; /**< Type to represent the distance between two iterators. */
@@ -388,6 +415,7 @@ struct _range_template : private std::conditional
     : _base_type(handle)
   {}
 
+  using _base_type::release_native_handle;
   using _base_type::native_handle;
   using _base_type::back;
   using _base_type::front;
index f0f22d9..45545c3 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef EFL_EINA_EINA_TUPLE_HH_
 #define EFL_EINA_EINA_TUPLE_HH_
 
+#include <eina_integer_sequence.hh>
+#include <eina_logical.hh>
+
+#include <tuple>
+
 namespace efl { namespace eina { namespace _mpl {
 
 template <typename A, typename... Args>
@@ -21,15 +26,64 @@ struct push_front<C<Args...>, AArgs...>
   typedef C<Args..., AArgs...> type;
 };
 
-template <typename A>
+template <typename A, std::size_t N = 1>
 struct pop_front;
-
+      
 template <template <typename...> class C, typename T, typename... Args>
-struct pop_front<C<T, Args...> >
+struct pop_front<C<T, Args...>, 1>
 {
   typedef C<Args...> type;
 };
 
+template <typename A, std::size_t N>
+struct pop_front : pop_front<typename pop_front<A, 1>::type, N-1>
+{
+};
+
+template <typename T, typename F, std::size_t... I>
+void for_each_impl(T&& t, F&& f, eina::index_sequence<I...>)
+{
+  std::initializer_list<int> l = { (f(std::get<I>(t)), 0)...};
+  static_cast<void>(l);
+}
+
+template <typename T, typename F>
+void for_each(T&& t, F&& f)
+{
+  _mpl::for_each_impl(t, f, eina::make_index_sequence
+                      <std::tuple_size<typename std::remove_reference<T>::type>::value>());
+}
+
+template <typename T, typename Transform>
+struct tuple_transform;
+
+template <typename...T, typename Transform>
+struct tuple_transform<std::tuple<T...>, Transform>
+{
+  typedef std::tuple<typename Transform::template apply<T>::type...> type;
+};
+
+template <typename T, typename Tuple>
+struct tuple_contains;
+
+
+      
+template <typename T, typename...Ts>
+struct tuple_contains<T, std::tuple<Ts...> >
+  : _mpl::or_<std::is_same<T, Ts>::value...>
+{
+};
+
+template <typename T, typename Tuple>
+struct tuple_find : std::integral_constant<int, -1> {};
+
+template <typename T, typename... Ts>
+struct tuple_find<T, std::tuple<T, Ts...> > : std::integral_constant<std::size_t, 0> {};
+
+template <typename T, typename T1, typename... Ts>
+struct tuple_find<T, std::tuple<T1, Ts...> > : std::integral_constant
+ <std::size_t, 1 + tuple_find<T, std::tuple<Ts...> >::value> {};
+      
 } } }
 
 #endif
diff --git a/src/bindings/eina_cxx/eina_tuple_c.hh b/src/bindings/eina_cxx/eina_tuple_c.hh
new file mode 100644 (file)
index 0000000..64d67c4
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef EFL_EINA_EINA_TUPLE_C_HH_
+#define EFL_EINA_EINA_TUPLE_C_HH_
+
+#include <tuple>
+
+namespace efl { namespace eina { namespace _mpl {
+
+template <typename T, T... Ts>
+using tuple_c = std::tuple<std::integral_constant<T, Ts>...>;
+
+template <typename T, T... Ts>
+constexpr std::size_t tuple_c_size(tuple_c<T, Ts...> const&)
+{
+  return sizeof...(Ts);
+}
+
+constexpr std::size_t tuple_c_size(std::tuple<> const&)
+{
+  return 0;
+}
+
+} } }
+
+#endif
index 9e8628a..ff8bfbb 100644 (file)
@@ -64,6 +64,22 @@ struct if_ : if_c<U::value, T, F>
 {
 };
 
+template <typename T>
+struct container_value_type
+{
+  typedef typename std::conditional<
+    std::is_void<T>::value
+    , T*, T>::type type;
+};
+
+template <typename T>
+struct nonconst_container_value_type
+{
+  typedef typename std::conditional<
+    std::is_void<T>::value
+    , T*, typename std::remove_const<T>::type>::type type;
+};
+
 /**
  * @}
  */
index e44b9b2..4af8c58 100644 (file)
@@ -11,7 +11,6 @@ namespace efl { namespace eldbus { namespace _detail {
 template <typename Callback, typename... Ins>
 void _callback_wrapper(void* data, Eldbus_Message const* message, Eldbus_Pending* pending)
 {
-  std::cout << "_callback_wrapper" << std::endl;
   Callback* callback(static_cast<Callback*>(data));
 
   const char* errname, *errmsg;
index 9e328b1..c975bbc 100644 (file)
@@ -187,6 +187,13 @@ struct concrete
    Eo* _eo_raw; ///< The opaque <em>EO Object</em>.
 };
 
+template<class CharT, class Traits>
+inline std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, concrete const& eo)
+{
+   return os << eo._eo_ptr();
+}
+
 inline bool operator==(concrete const& lhs, concrete const& rhs)
 {
   return lhs._eo_ptr() == rhs._eo_ptr();
diff --git a/src/bindings/js/ecore_js/Ecore_Js.hh b/src/bindings/js/ecore_js/Ecore_Js.hh
new file mode 100644 (file)
index 0000000..3f877f3
--- /dev/null
@@ -0,0 +1,58 @@
+
+#ifndef EFL_ECORE_JS_HH
+#define EFL_ECORE_JS_HH
+
+#include <Ecore.hh>
+#include <Ecore_File.h>
+#include <Eina_Js.hh>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_JS_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+namespace efl { namespace ecore { namespace js {
+
+using ::efl::eina::js::compatibility_new;
+using ::efl::eina::js::compatibility_return_type;
+using ::efl::eina::js::compatibility_callback_info_type;
+using ::efl::eina::js::compatibility_return;
+using ::efl::eina::js::compatibility_get_pointer_internal_field;
+using ::efl::eina::js::compatibility_set_pointer_internal_field;
+
+EAPI void register_ecore_animator(v8::Isolate *isolate,v8::Handle<v8::Object> exports);
+EAPI void register_ecore_event(v8::Isolate* isolate, v8::Handle<v8::Object> exports);
+EAPI void register_ecore_file(v8::Isolate* isolate, v8::Handle<v8::Object> exports);
+EAPI void register_ecore_idle(v8::Isolate *isolate,v8::Handle<v8::Object> exports);
+EAPI void register_ecore_job(v8::Isolate *isolate,v8::Handle<v8::Object> exports);
+EAPI void register_ecore_mainloop(v8::Isolate *isolate,v8::Handle<v8::Object> exports);
+EAPI void register_ecore_poller(v8::Isolate *isolate,v8::Handle<v8::Object> exports);
+EAPI void register_ecore_throttle(v8::Isolate *isolate,v8::Handle<v8::Object> exports);
+EAPI void register_ecore_timer(v8::Isolate *isolate,v8::Handle<v8::Object> exports);
+
+EAPI void register_ecore(v8::Isolate *isolate,v8::Handle<v8::Object> exports);
+
+} } }
+
+#endif
diff --git a/src/bindings/js/ecore_js/ecore_js_animator.cc b/src/bindings/js/ecore_js/ecore_js_animator.cc
new file mode 100644 (file)
index 0000000..849e4d7
--- /dev/null
@@ -0,0 +1,608 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Ecore_Js.hh>
+
+namespace efl { namespace ecore { namespace js {
+
+static Ecore_Animator* extract_animator(v8::Local<v8::Object> object)
+{
+    auto ptr = v8::External::Cast(*object->GetInternalField(0))->Value();
+    return reinterpret_cast<Ecore_Animator*>(ptr);
+}
+
+static v8::Local<v8::Object> wrap_animator(Ecore_Animator *animator,
+                                           v8::Isolate *isolate)
+{
+    using v8::Boolean;
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_animator_del(extract_animator(info.This()));
+        return compatibility_return();
+    };
+
+    auto freeze = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_animator_freeze(extract_animator(info.This()));
+        return compatibility_return();
+    };
+
+    auto thaw = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_animator_thaw(extract_animator(info.This()));
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "freeze"),
+             compatibility_new<FunctionTemplate>(isolate, freeze)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "thaw"),
+             compatibility_new<FunctionTemplate>(isolate, thaw)->GetFunction());
+
+    ret->SetInternalField(0, compatibility_new<v8::External>(isolate,
+                                                             animator));
+
+    return ret;
+}
+
+void register_pos_map_linear(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_POS_MAP_LINEAR));
+}
+
+void register_pos_map_accelerate(v8::Isolate *isolate,
+                                 v8::Handle<v8::Object> global,
+                                 v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_POS_MAP_ACCELERATE));
+}
+
+void register_pos_map_decelerate(v8::Isolate *isolate,
+                                 v8::Handle<v8::Object> global,
+                                 v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_POS_MAP_DECELERATE));
+}
+
+void register_pos_map_sinusoidal(v8::Isolate *isolate,
+                                 v8::Handle<v8::Object> global,
+                                 v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_POS_MAP_SINUSOIDAL));
+}
+
+void register_pos_map_accelerate_factor(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ECORE_POS_MAP_ACCELERATE_FACTOR));
+}
+
+void register_pos_map_decelerate_factor(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ECORE_POS_MAP_DECELERATE_FACTOR));
+}
+
+void register_pos_map_sinusoidal_factor(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ECORE_POS_MAP_SINUSOIDAL_FACTOR));
+}
+
+void register_pos_map_divisor_interp(v8::Isolate *isolate,
+                                     v8::Handle<v8::Object> global,
+                                     v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ECORE_POS_MAP_DIVISOR_INTERP));
+}
+
+void register_pos_map_bounce(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_POS_MAP_BOUNCE));
+}
+
+void register_pos_map_spring(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_POS_MAP_SPRING));
+}
+
+void register_pos_map_cubic_bezier(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ECORE_POS_MAP_CUBIC_BEZIER));
+}
+
+void register_animator_source_timer(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ECORE_ANIMATOR_SOURCE_TIMER));
+}
+
+void register_animator_frametime_set(v8::Isolate *isolate,
+                                     v8::Handle<v8::Object> global,
+                                     v8::Handle<v8::String> name)
+{
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        ecore_animator_frametime_set(args[0]->NumberValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_animator_frametime_get(v8::Isolate *isolate,
+                                     v8::Handle<v8::Object> global,
+                                     v8::Handle<v8::String> name)
+{
+    using v8::Number;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_animator_frametime_get();
+        return compatibility_return(compatibility_new<Number>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_animator_pos_map(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Number;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 4 || !args[0]->IsNumber() || !args[1]->IsNumber()
+            || !args[2]->IsNumber() || !args[3]->IsNumber())
+            return compatibility_return();
+
+        Ecore_Pos_Map map;
+
+        switch ((int)(args[1]->NumberValue())) {
+        case ECORE_POS_MAP_LINEAR:
+            map = ECORE_POS_MAP_LINEAR;
+            break;
+        case ECORE_POS_MAP_ACCELERATE:
+            map = ECORE_POS_MAP_ACCELERATE;
+            break;
+        case ECORE_POS_MAP_DECELERATE:
+            map = ECORE_POS_MAP_DECELERATE;
+            break;
+        case ECORE_POS_MAP_SINUSOIDAL:
+            map = ECORE_POS_MAP_SINUSOIDAL;
+            break;
+        case ECORE_POS_MAP_ACCELERATE_FACTOR:
+            map = ECORE_POS_MAP_ACCELERATE_FACTOR;
+            break;
+        case ECORE_POS_MAP_DECELERATE_FACTOR:
+            map = ECORE_POS_MAP_DECELERATE_FACTOR;
+            break;
+        case ECORE_POS_MAP_SINUSOIDAL_FACTOR:
+            map = ECORE_POS_MAP_SINUSOIDAL_FACTOR;
+            break;
+        case ECORE_POS_MAP_DIVISOR_INTERP:
+            map = ECORE_POS_MAP_DIVISOR_INTERP;
+            break;
+        case ECORE_POS_MAP_BOUNCE:
+            map = ECORE_POS_MAP_BOUNCE;
+            break;
+        case ECORE_POS_MAP_SPRING:
+            map = ECORE_POS_MAP_SPRING;
+            break;
+        case ECORE_POS_MAP_CUBIC_BEZIER:
+            map = ECORE_POS_MAP_CUBIC_BEZIER;
+            break;
+        default:
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_animator_pos_map(args[0]->NumberValue(), map,
+                                          args[2]->NumberValue(),
+                                          args[3]->NumberValue());
+        return compatibility_return(compatibility_new<Number>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_animator_pos_map_n(v8::Isolate *isolate,
+                                 v8::Handle<v8::Object> global,
+                                 v8::Handle<v8::String> name)
+{
+    using v8::Number;
+    using v8::NumberObject;
+    using v8::FunctionTemplate;
+    using v8::Array;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 3 || !args[0]->IsNumber() || !args[1]->IsNumber()
+            || !args[2]->IsArray())
+            return compatibility_return();
+
+        Ecore_Pos_Map map;
+
+        switch ((int)(args[1]->NumberValue())) {
+        case ECORE_POS_MAP_LINEAR:
+            map = ECORE_POS_MAP_LINEAR;
+            break;
+        case ECORE_POS_MAP_ACCELERATE:
+            map = ECORE_POS_MAP_ACCELERATE;
+            break;
+        case ECORE_POS_MAP_DECELERATE:
+            map = ECORE_POS_MAP_DECELERATE;
+            break;
+        case ECORE_POS_MAP_SINUSOIDAL:
+            map = ECORE_POS_MAP_SINUSOIDAL;
+            break;
+        case ECORE_POS_MAP_ACCELERATE_FACTOR:
+            map = ECORE_POS_MAP_ACCELERATE_FACTOR;
+            break;
+        case ECORE_POS_MAP_DECELERATE_FACTOR:
+            map = ECORE_POS_MAP_DECELERATE_FACTOR;
+            break;
+        case ECORE_POS_MAP_SINUSOIDAL_FACTOR:
+            map = ECORE_POS_MAP_SINUSOIDAL_FACTOR;
+            break;
+        case ECORE_POS_MAP_DIVISOR_INTERP:
+            map = ECORE_POS_MAP_DIVISOR_INTERP;
+            break;
+        case ECORE_POS_MAP_BOUNCE:
+            map = ECORE_POS_MAP_BOUNCE;
+            break;
+        case ECORE_POS_MAP_SPRING:
+            map = ECORE_POS_MAP_SPRING;
+            break;
+        case ECORE_POS_MAP_CUBIC_BEZIER:
+            map = ECORE_POS_MAP_CUBIC_BEZIER;
+            break;
+        default:
+            return compatibility_return();
+        }
+
+        std::vector<double> v;
+        {
+            auto array = Array::Cast(*args[2]);
+            auto s = array->Length();
+            v.reserve(s);
+            for (decltype(s) i = 0;i != s;++i) {
+                auto e = array->Get(i);
+                if (!e->IsNumber())
+                    return compatibility_return();
+
+                v.push_back(e->NumberValue());
+            }
+        }
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_animator_pos_map_n(args[0]->NumberValue(), map,
+                                            v.size(), v.data());
+        return compatibility_return(compatibility_new<Number>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_animator_source_set(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name)
+{
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        Ecore_Animator_Source source;
+
+        switch ((int)(args[0]->NumberValue())) {
+        case ECORE_ANIMATOR_SOURCE_TIMER:
+            source = ECORE_ANIMATOR_SOURCE_TIMER;
+            break;
+        case ECORE_ANIMATOR_SOURCE_CUSTOM:
+            source = ECORE_ANIMATOR_SOURCE_CUSTOM;
+            break;
+        default:
+            return compatibility_return();
+        }
+
+        ecore_animator_source_set(source);
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_animator_source_get(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_animator_source_get();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_animator_add(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                           v8::Handle<v8::String> name)
+{
+    using v8::Local;
+    using v8::Value;
+    using v8::Undefined;
+    using v8::Function;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto f = new efl::eina::js::global_ref<Value>(isolate, args[0]);
+
+        auto cb = [](void *data) -> Eina_Bool {
+            auto persistent = static_cast<efl::eina::js::global_ref<Value>*>(data);
+            auto o = persistent->handle();
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 0, NULL);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            if (!bret)
+            {
+              persistent->dispose();
+              delete persistent;
+            }
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto ret = ecore_animator_add(cb, f);
+        return compatibility_return(wrap_animator(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_animator_timeline_add(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name)
+{
+    using v8::Handle;
+    using v8::Local;
+    using v8::Value;
+    using v8::Undefined;
+    using v8::Function;
+    using v8::FunctionTemplate;
+    using v8::Number;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 2 || !args[0]->IsNumber()
+            || !args[1]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto f = new efl::eina::js::global_ref<Value>(args.GetIsolate(), args[1]);
+
+        auto cb = [](void *data, double pos) -> Eina_Bool {
+            auto persistent
+              = reinterpret_cast<efl::eina::js::global_ref<Value>*>(data);
+            auto o = persistent->handle();
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = compatibility_new<Number>(isolate, pos);
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            if (!bret)
+              {
+                 persistent->dispose();
+                 delete persistent;
+              }
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto ret = ecore_animator_timeline_add(args[0]->NumberValue(), cb, f);
+        return compatibility_return(wrap_animator(ret, args.GetIsolate()),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_ecore_animator(v8::Isolate* isolate, v8::Handle<v8::Object> exports)
+{
+   register_pos_map_linear(isolate, exports,
+                           compatibility_new<v8::String>(isolate,
+                                                     "ECORE_POS_MAP_LINEAR"));
+   register_pos_map_accelerate(isolate, exports,
+                               compatibility_new<v8::String>(isolate,
+                                                         "ECORE_POS_MAP"
+                                                         "_ACCELERATE"));
+   register_pos_map_decelerate(isolate, exports,
+                               compatibility_new<v8::String>(isolate,
+                                                         "ECORE_POS_MAP"
+                                                         "_DECELERATE"));
+   register_pos_map_sinusoidal(isolate, exports,
+                               compatibility_new<v8::String>(isolate,
+                                                         "ECORE_POS_MAP"
+                                                         "_SINUSOIDAL"));
+   register_pos_map_accelerate_factor(isolate, exports,
+                                      compatibility_new<v8::String>(isolate,
+                                                                "ECORE_POS_MAP"
+                                                                "_ACCELERATE"
+                                                                "_FACTOR"));
+   register_pos_map_decelerate_factor(isolate, exports,
+                                      compatibility_new<v8::String>(isolate,
+                                                                "ECORE_POS_MAP"
+                                                                "_DECELERATE"
+                                                                "_FACTOR"));
+   register_pos_map_sinusoidal_factor(isolate, exports,
+                                      compatibility_new<v8::String>(isolate,
+                                                                "ECORE_POS_MAP"
+                                                                "_SINUSOIDAL"
+                                                                "_FACTOR"));
+   register_pos_map_divisor_interp(isolate, exports,
+                                   compatibility_new<v8::String>(isolate,
+                                                             "ECORE_POS_MAP"
+                                                             "_DIVISOR_INTERP"));
+   register_pos_map_bounce(isolate, exports,
+                           compatibility_new<v8::String>(isolate,
+                                                     "ECORE_POS_MAP_BOUNCE"));
+   register_pos_map_spring(isolate, exports,
+                           compatibility_new<v8::String>(isolate,
+                                                     "ECORE_POS_MAP_SPRING"));
+   register_pos_map_cubic_bezier(isolate, exports,
+                                 compatibility_new<v8::String>(isolate,
+                                                           "ECORE_POS_MAP_CUBIC"
+                                                           "_BEZIER"));
+   register_animator_source_timer(isolate, exports,
+                                  compatibility_new<v8::String>(isolate,
+                                                            "ECORE_ANIMATOR"
+                                                            "_SOURCE_TIMER"));
+   register_animator_frametime_set(isolate, exports,
+                                   compatibility_new<v8::String>(isolate,
+                                                             "ecore_animator"
+                                                             "_frametime_set"));
+   register_animator_frametime_get(isolate, exports,
+                                   compatibility_new<v8::String>(isolate,
+                                                             "ecore_animator"
+                                                             "_frametime_get"));
+   register_animator_pos_map(isolate, exports,
+                             compatibility_new<v8::String>(isolate,
+                                                       "ecore_animator_pos"
+                                                       "_map"));
+   register_animator_pos_map_n(isolate, exports,
+                               compatibility_new<v8::String>(isolate,
+                                                         "ecore_animator_pos_map"
+                                                         "_n"));
+   register_animator_source_set(isolate, exports,
+                                compatibility_new<v8::String>(isolate,
+                                                          "ecore_animator_source"
+                                                          "_set"));
+   register_animator_source_get(isolate, exports,
+                                compatibility_new<v8::String>(isolate,
+                                                          "ecore_animator_source"
+                                                          "_get"));
+   register_animator_add(isolate, exports,
+                         compatibility_new<v8::String>(isolate,
+                                                   "ecore_animator_add"));
+   register_animator_timeline_add(isolate, exports,
+                                  compatibility_new<v8::String>(isolate,
+                                                            "ecore_animator"
+                                                            "_timeline_add"));
+}   
+      
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/ecore_js/ecore_js_event.cc b/src/bindings/js/ecore_js/ecore_js_event.cc
new file mode 100644 (file)
index 0000000..a086d98
--- /dev/null
@@ -0,0 +1,772 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Ecore_Js.hh>
+
+namespace efl { namespace ecore { namespace js {
+
+static Ecore_Event *extract_event(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field<Ecore_Event*>(object, 0);
+}
+
+static v8::Local<v8::Object> wrap_event(Ecore_Event *event,
+                                        v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_event_del(extract_event(info.This()));
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, event);
+
+    return ret;
+}
+
+static Ecore_Event_Handler *extract_event_handler(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field<Ecore_Event_Handler*>
+        (object, 0);
+}
+
+static v8::Local<v8::Object> wrap_event_handler(Ecore_Event_Handler *handler,
+                                                v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+    using v8::Value;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto p = ecore_event_handler_del(extract_event_handler(info.This()));
+
+        delete static_cast<efl::eina::js::global_ref<Value>*>(p);
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, handler);
+
+    return ret;
+}
+
+static Ecore_Event_Filter *extract_event_filter(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field<Ecore_Event_Filter*>
+        (object, 0);
+}
+
+static v8::Local<v8::Object> wrap_event_filter(Ecore_Event_Filter *filter,
+                                               v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+    using v8::Value;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto p = ecore_event_filter_del(extract_event_filter(info.This()));
+        delete[] static_cast<efl::eina::js::global_ref<Value>*>(p);
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, filter);
+
+    return ret;
+}
+
+EAPI
+void register_event_none(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                         v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_EVENT_NONE));
+}
+
+EAPI
+void register_event_signal_user(v8::Isolate *isolate,
+                                v8::Handle<v8::Object> global,
+                                v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_EVENT_SIGNAL_USER));
+}
+
+EAPI
+void register_event_signal_hup(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_EVENT_SIGNAL_HUP));
+}
+
+EAPI
+void register_event_signal_exit(v8::Isolate *isolate,
+                                v8::Handle<v8::Object> global,
+                                v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_EVENT_SIGNAL_EXIT));
+}
+
+EAPI
+void register_event_signal_power(v8::Isolate *isolate,
+                                 v8::Handle<v8::Object> global,
+                                 v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_EVENT_SIGNAL_POWER));
+}
+
+EAPI
+void register_event_signal_realtime(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ECORE_EVENT_SIGNAL_REALTIME));
+}
+
+EAPI
+void register_event_memory_state(v8::Isolate *isolate,
+                                 v8::Handle<v8::Object> global,
+                                 v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_EVENT_MEMORY_STATE));
+}
+
+EAPI
+void register_event_power_state(v8::Isolate *isolate,
+                                v8::Handle<v8::Object> global,
+                                v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_EVENT_POWER_STATE));
+}
+
+EAPI
+void register_event_locale_changed(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ECORE_EVENT_LOCALE_CHANGED));
+}
+
+EAPI
+void register_event_hostname_changed(v8::Isolate *isolate,
+                                     v8::Handle<v8::Object> global,
+                                     v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ECORE_EVENT_HOSTNAME_CHANGED));
+}
+
+EAPI
+void register_event_system_timedate_changed(v8::Isolate *isolate,
+                                            v8::Handle<v8::Object> global,
+                                            v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED));
+}
+
+EAPI
+void register_event_type_new(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_event_type_new();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_event_add(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                        v8::Handle<v8::String> name)
+{
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_event_add(args[0]->NumberValue(), NULL, NULL, NULL);
+        return compatibility_return(wrap_event(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_event_handler_add(v8::Isolate *isolate,
+                                v8::Handle<v8::Object> global,
+                                v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::Value;
+    using v8::Function;
+    using v8::Handle;
+    using v8::Local;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 2 || !args[0]->IsNumber()
+            || !args[1]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto p = new efl::eina::js::global_ref<Value>(isolate, args[1]);
+
+        auto cb = [](void *d, int type, void */*event*/) -> Eina_Bool {
+            auto persistent = static_cast<efl::eina::js::global_ref<Value>*>(d);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+            Handle<Value> args = compatibility_new<Integer>(isolate, type);
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto ret = ecore_event_handler_add(args[0]->Int32Value(), cb, p);
+        return compatibility_return(wrap_event_handler(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_event_filter_add(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::Value;
+    using v8::Function;
+    using v8::Handle;
+    using v8::Local;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 3 || !args[0]->IsFunction()
+            || !args[1]->IsFunction() || !args[2]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto p = new efl::eina::js::global_ref<Value>[3]{{isolate, args[0]},
+                                                         {isolate, args[1]},
+                                                         {isolate, args[2]}};
+
+        auto start_cb = [](void *data) -> void* {
+            auto p = static_cast<efl::eina::js::global_ref<Value>*>(data);
+            auto isolate = v8::Isolate::GetCurrent();
+            auto o = p->handle();
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 0, NULL);
+            return new efl::eina::js::global_ref<Value>{isolate, ret};
+        };
+
+        auto filter_cb = [](void *data, void *loop_data, int type,
+                            void */*event*/) -> Eina_Bool {
+            typedef efl::eina::js::global_ref<Value> p_t;
+
+            auto p = static_cast<p_t*>(data) + 1;
+            auto isolate = v8::Isolate::GetCurrent();
+            auto o = p->handle();
+
+            Handle<Value> args[2]{
+                static_cast<p_t*>(loop_data)->handle(),
+                compatibility_new<Integer>(isolate, type)
+            };
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 2, args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto end_cb = [](void *user_data, void *func_data) -> void {
+            typedef efl::eina::js::global_ref<Value> p_t;
+
+            auto loop_data = std::unique_ptr<p_t>(static_cast<p_t*>
+                                                  (func_data));
+            auto p = static_cast<p_t*>(user_data) + 2;
+            auto o = p->handle();
+
+            Handle<Value> args = p->handle();
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+        };
+
+        auto ret = ecore_event_filter_add(start_cb, filter_cb, end_cb, p);
+        return compatibility_return(wrap_event_filter(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_event_current_type_get(v8::Isolate *isolate,
+                                     v8::Handle<v8::Object> global,
+                                     v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_event_current_type_get();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_memory_state_normal(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_MEMORY_STATE_NORMAL));
+}
+
+EAPI
+void register_memory_state_low(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_MEMORY_STATE_LOW));
+}
+
+EAPI
+void register_power_state_mains(v8::Isolate *isolate,
+                                v8::Handle<v8::Object> global,
+                                v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_POWER_STATE_MAINS));
+}
+
+EAPI
+void register_power_state_battery(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_POWER_STATE_BATTERY));
+}
+
+EAPI
+void register_power_state_low(v8::Isolate *isolate,
+                              v8::Handle<v8::Object> global,
+                              v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ECORE_POWER_STATE_LOW));
+}
+
+EAPI
+void register_memory_state_get(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_memory_state_get();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_power_state_get(v8::Isolate *isolate,
+                                     v8::Handle<v8::Object> global,
+                                     v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_power_state_get();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_event_signal_user_handler_add(v8::Isolate *isolate,
+                                            v8::Handle<v8::Object> global,
+                                            v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::String;
+    using v8::Value;
+    using v8::Object;
+    using v8::Function;
+    using v8::Handle;
+    using v8::Local;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+
+        auto p = new efl::eina::js::global_ref<Value>(isolate, args[0]);
+
+        auto cb = [](void *d, int type, void *event) -> Eina_Bool {
+            auto p = static_cast<efl::eina::js::global_ref<Value>*>(d);
+            auto isolate = v8::Isolate::GetCurrent();
+            auto o = p->handle();
+
+            auto wrapped_event = compatibility_new<Object>(isolate);
+
+            {
+                auto n
+                    = reinterpret_cast<Ecore_Event_Signal_User*>(event)->number;
+                wrapped_event->Set(compatibility_new<String>(isolate, "number"),
+                                   compatibility_new<Integer>(isolate, n));
+            }
+
+            Handle<Value> args[2]{
+                compatibility_new<Integer>(isolate, type),
+                wrapped_event
+            };
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 2, args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto ret = ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER, cb, p);
+        return compatibility_return(wrap_event_handler(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_event_signal_exit_handler_add(v8::Isolate *isolate,
+                                            v8::Handle<v8::Object> global,
+                                            v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::Boolean;
+    using v8::String;
+    using v8::Value;
+    using v8::Object;
+    using v8::Function;
+    using v8::Handle;
+    using v8::Local;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+
+        auto p = new efl::eina::js::global_ref<Value>(isolate, args[0]);
+
+        auto cb = [](void *d, int type, void *ev) -> Eina_Bool {
+            auto p = static_cast<efl::eina::js::global_ref<Value>*>(d);
+            auto isolate = v8::Isolate::GetCurrent();
+            auto o = p->handle();
+
+            auto wrapped_event = compatibility_new<Object>(isolate);
+
+            {
+                auto event = reinterpret_cast<Ecore_Event_Signal_Exit*>(ev);
+                auto interrupt = event->interrupt;
+                auto quit = event->quit;
+                auto terminate = event->terminate;
+
+                wrapped_event->Set(compatibility_new<String>(isolate,
+                                                             "interrupt"),
+                                   compatibility_new<Boolean>(isolate,
+                                                              interrupt));
+                wrapped_event->Set(compatibility_new<String>(isolate, "quit"),
+                                   compatibility_new<Boolean>(isolate, quit));
+                wrapped_event->Set(compatibility_new<String>(isolate,
+                                                             "terminate"),
+                                   compatibility_new<Boolean>(isolate,
+                                                              terminate));
+            }
+
+            Handle<Value> args[2]{
+                compatibility_new<Integer>(isolate, type),
+                wrapped_event
+            };
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 2, args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto ret = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, cb, p);
+        return compatibility_return(wrap_event_handler(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_event_signal_realtime_handler_add(v8::Isolate *isolate,
+                                                v8::Handle<v8::Object> global,
+                                                v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::String;
+    using v8::Value;
+    using v8::Object;
+    using v8::Function;
+    using v8::Handle;
+    using v8::Local;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+
+        auto p = new efl::eina::js::global_ref<Value>(isolate, args[0]);
+
+        auto cb = [](void *d, int type, void *ev) -> Eina_Bool {
+            auto p = static_cast<efl::eina::js::global_ref<Value>*>(d);
+            auto isolate = v8::Isolate::GetCurrent();
+            auto o = p->handle();
+
+            auto wrapped_event = compatibility_new<Object>(isolate);
+
+            {
+                auto n
+                    = reinterpret_cast<Ecore_Event_Signal_Realtime*>(ev)->num;
+                wrapped_event->Set(compatibility_new<String>(isolate, "num"),
+                                   compatibility_new<Integer>(isolate, n));
+            }
+
+            Handle<Value> args[2]{
+                compatibility_new<Integer>(isolate, type),
+                wrapped_event
+            };
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 2, args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto ret = ecore_event_handler_add(ECORE_EVENT_SIGNAL_REALTIME, cb, p);
+        return compatibility_return(wrap_event_handler(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_ecore_event(v8::Isolate* isolate, v8::Handle<v8::Object> exports)
+{
+   register_event_none(isolate, exports,
+                       compatibility_new<v8::String>(isolate,
+                                                 "ECORE_EVENT_NONE"));
+   register_event_signal_user(isolate, exports,
+                              compatibility_new<v8::String>
+                              (isolate, "ECORE_EVENT_SIGNAL_USER"));
+   register_event_signal_hup(isolate, exports,
+                             compatibility_new<v8::String>
+                             (isolate, "ECORE_EVENT_SIGNAL_HUP"));
+   register_event_signal_exit(isolate, exports,
+                              compatibility_new<v8::String>
+                              (isolate, "ECORE_EVENT_SIGNAL_EXIT"));
+   register_event_signal_power(isolate, exports,
+                               compatibility_new<v8::String>
+                               (isolate, "ECORE_EVENT_SIGNAL_POWER"));
+   register_event_signal_realtime(isolate, exports,
+                                  compatibility_new<v8::String>
+                                  (isolate, "ECORE_EVENT_SIGNAL_REALTIME"));
+   register_event_memory_state(isolate, exports,
+                               compatibility_new<v8::String>
+                               (isolate, "ECORE_EVENT_MEMORY_STATE"));
+   register_event_power_state(isolate, exports,
+                              compatibility_new<v8::String>
+                              (isolate, "ECORE_EVENT_POWER_STATE"));
+   register_event_locale_changed(isolate, exports,
+                                 compatibility_new<v8::String>
+                                 (isolate, "ECORE_EVENT_LOCALE_CHANGED"));
+   register_event_hostname_changed(isolate, exports,
+                                   compatibility_new<v8::String>
+                                   (isolate, "ECORE_EVENT_HOSTNAME_CHANGED"));
+   register_event_system_timedate_changed(isolate, exports,
+                                          compatibility_new<v8::String>
+                                          (isolate,
+                                           "ECORE_EVENT_SYSTEM_TIMEDATE"
+                                           "_CHANGED"));
+   register_event_type_new(isolate, exports,
+                           compatibility_new<v8::String>(isolate,
+                                                     "ecore_event_type_new"));
+   register_event_add(isolate, exports,
+                      compatibility_new<v8::String>(isolate, "ecore_event_add"));
+   register_event_handler_add(isolate, exports,
+                              compatibility_new<v8::String>
+                              (isolate, "ecore_event_handler_add"));
+   register_event_filter_add(isolate, exports,
+                             compatibility_new<v8::String>
+                             (isolate, "ecore_event_filter_add"));
+   register_event_current_type_get(isolate, exports,
+                                   compatibility_new<v8::String>
+                                   (isolate, "ecore_event_current_type_get"));
+   register_memory_state_normal(isolate, exports,
+                                compatibility_new<v8::String>
+                                (isolate, "ECORE_MEMORY_STATE_NORMAL"));
+   register_memory_state_low(isolate, exports,
+                             compatibility_new<v8::String>
+                             (isolate, "ECORE_MEMORY_STATE_LOW"));
+   register_power_state_mains(isolate, exports,
+                              compatibility_new<v8::String>
+                              (isolate, "ECORE_POWER_STATE_MAINS"));
+   register_power_state_battery(isolate, exports,
+                                compatibility_new<v8::String>
+                                (isolate, "ECORE_POWER_STATE_BATTERY"));
+   register_power_state_low(isolate, exports,
+                            compatibility_new<v8::String>(isolate,
+                                                      "ECORE_POWER_STATE_LOW"));
+   register_event_signal_user_handler_add(isolate, exports,
+                                          compatibility_new<v8::String>
+                                          (isolate,
+                                           "ecore_event_signal_user_handler"
+                                           "_add"));
+   register_event_signal_exit_handler_add(isolate, exports,
+                                          compatibility_new<v8::String>
+                                          (isolate,
+                                           "ecore_event_signal_exit_handler"
+                                           "_add"));
+   register_event_signal_realtime_handler_add(isolate, exports,
+                                              compatibility_new<v8::String>
+                                              (isolate,
+                                               "ecore_event_signal_realtime"
+                                               "_handler_add"));
+}
+      
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/ecore_js/ecore_js_idle.cc b/src/bindings/js/ecore_js/ecore_js_idle.cc
new file mode 100644 (file)
index 0000000..293cef2
--- /dev/null
@@ -0,0 +1,294 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Ecore_Js.hh>
+
+namespace efl { namespace ecore { namespace js {
+
+static Ecore_Idler* extract_idler(v8::Local<v8::Object> object)
+{
+    auto ptr = v8::External::Cast(*object->GetInternalField(0))->Value();
+    return reinterpret_cast<Ecore_Idler*>(ptr);
+}
+
+static
+v8::Local<v8::Object> wrap_idler(Ecore_Idler *idler, v8::Isolate *isolate)
+{
+    using v8::Boolean;
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_idler_del(extract_idler(info.This()));
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    ret->SetInternalField(0, compatibility_new<v8::External>(isolate, idler));
+
+    return ret;
+}
+
+static Ecore_Idle_Enterer* extract_idle_enterer(v8::Local<v8::Object> object)
+{
+    auto ptr = v8::External::Cast(*object->GetInternalField(0))->Value();
+    return reinterpret_cast<Ecore_Idle_Enterer*>(ptr);
+}
+
+static v8::Local<v8::Object> wrap_idle_enterer(Ecore_Idle_Enterer *idle_enterer,
+                                               v8::Isolate *isolate)
+{
+    using v8::Boolean;
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+    using v8::External;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_idle_enterer_del(extract_idle_enterer(info.This()));
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    ret->SetInternalField(0,
+                          compatibility_new<External>(isolate, idle_enterer));
+
+    return ret;
+}
+
+static Ecore_Idle_Exiter* extract_idle_exiter(v8::Local<v8::Object> object)
+{
+    auto ptr = v8::External::Cast(*object->GetInternalField(0))->Value();
+    return reinterpret_cast<Ecore_Idle_Exiter*>(ptr);
+}
+
+static v8::Local<v8::Object> wrap_idle_exiter(Ecore_Idle_Exiter *idle_exiter,
+                                              v8::Isolate *isolate)
+{
+    using v8::Boolean;
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+    using v8::External;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_idle_exiter_del(extract_idle_exiter(info.This()));
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    ret->SetInternalField(0, compatibility_new<External>(isolate, idle_exiter));
+
+    return ret;
+}
+
+void register_idler_add(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                        v8::Handle<v8::String> name)
+{
+    using v8::Local;
+    using v8::Value;
+    using v8::Undefined;
+    using v8::Function;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto f = new efl::eina::js::global_ref<Value>(args.GetIsolate(), args[0]);
+        auto ret = ecore_idler_add([](void *data) -> Eina_Bool {
+            auto persistent = static_cast<efl::eina::js::global_ref<Value>*>(data);
+            auto o = persistent->handle();
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 0, NULL);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            if (!bret)
+              {
+                 persistent->dispose();
+                 delete persistent;
+              }
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        }, f);
+
+        return compatibility_return(wrap_idler(ret, args.GetIsolate()), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_idle_enterer_add(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Local;
+    using v8::Value;
+    using v8::Undefined;
+    using v8::Function;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto f = new efl::eina::js::global_ref<Value>(args.GetIsolate(), args[0]);
+    auto ret = ecore_idle_enterer_add([](void *data) -> Eina_Bool {
+            auto persistent = static_cast<efl::eina::js::global_ref<Value>*>(data);
+            auto o = persistent->handle();
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 0, NULL);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            if (!bret)
+              {
+                 persistent->dispose();
+                 delete persistent;
+              }
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        }, f);
+
+        return compatibility_return(wrap_idle_enterer(ret, args.GetIsolate()),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_idle_enterer_before_add(v8::Isolate *isolate,
+                                      v8::Handle<v8::Object> global,
+                                      v8::Handle<v8::String> name)
+{
+    using v8::Local;
+    using v8::Value;
+    using v8::Undefined;
+    using v8::Function;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto f = new efl::eina::js::global_ref<Value>(args.GetIsolate(), args[0]);
+        auto ret = ecore_idle_enterer_before_add([](void *data) -> Eina_Bool {
+            auto persistent = static_cast<efl::eina::js::global_ref<Value>*>(data);
+            auto o = persistent->handle();
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 0, NULL);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            if (!bret)
+              {
+                 persistent->dispose();
+                 delete persistent;
+              }
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        }, f);
+
+        return compatibility_return(wrap_idle_enterer(ret, args.GetIsolate()),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_idle_exiter_add(v8::Isolate *isolate,
+                              v8::Handle<v8::Object> global,
+                              v8::Handle<v8::String> name)
+{
+    using v8::Local;
+    using v8::Value;
+    using v8::Undefined;
+    using v8::Function;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto f = new efl::eina::js::global_ref<Value>(args.GetIsolate(), args[0]);
+        auto ret = ecore_idle_exiter_add([](void *data) -> Eina_Bool {
+            auto persistent = static_cast<efl::eina::js::global_ref<Value>*>(data);
+            auto o = persistent->handle();
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 0, NULL);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            if (!bret)
+              {
+                 persistent->dispose();
+                 delete persistent;
+              }
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        }, f);
+
+        return compatibility_return(wrap_idle_exiter(ret, args.GetIsolate()),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_ecore_idle(v8::Isolate *isolate,v8::Handle<v8::Object> exports)
+{
+   register_idler_add(isolate, exports,
+                      compatibility_new<v8::String>(isolate, "ecore_idler_add"));
+   register_idle_enterer_add(isolate, exports,
+                             compatibility_new<v8::String>(isolate,
+                                                       "ecore_idle_enterer"
+                                                       "_add"));
+   register_idle_enterer_before_add(isolate, exports,
+                                    compatibility_new<v8::String>(isolate,
+                                                              "ecore_idle"
+                                                              "_enterer_before"
+                                                              "_add"));
+   register_idle_exiter_add(isolate, exports,
+                            compatibility_new<v8::String>(isolate,
+                                                      "ecore_idle_exiter_add"));
+}
+
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/ecore_js/ecore_js_init.cc b/src/bindings/js/ecore_js/ecore_js_init.cc
new file mode 100644 (file)
index 0000000..ba2b04f
--- /dev/null
@@ -0,0 +1,76 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Ecore_Js.hh>
+
+namespace efl { namespace ecore { namespace js {
+
+namespace {
+
+void register_init(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                   v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto init = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ::ecore_init();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, init)
+                ->GetFunction());
+}
+
+void register_shutdown(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                       v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto shutdown = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_shutdown();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, shutdown)
+                ->GetFunction());
+}
+
+}
+
+EAPI
+void register_ecore(v8::Isolate *isolate,v8::Handle<v8::Object> exports)
+{
+   efl::ecore::js::register_init(isolate, exports,
+                                 efl::eina::js::compatibility_new<v8::String>
+                                 (isolate, "ecore_init"));
+   efl::ecore::js::register_shutdown(isolate, exports,
+                                     efl::eina::js::compatibility_new<v8::String>
+                                     (isolate, "ecore_shutdown"));
+   register_ecore_animator(isolate, exports);
+   register_ecore_event(isolate, exports);
+   register_ecore_idle(isolate, exports);
+   register_ecore_job(isolate, exports);
+   register_ecore_mainloop(isolate, exports);
+   register_ecore_poller(isolate, exports);
+   register_ecore_throttle(isolate, exports);
+   register_ecore_timer(isolate, exports);
+}
+      
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/ecore_js/ecore_js_job.cc b/src/bindings/js/ecore_js/ecore_js_job.cc
new file mode 100644 (file)
index 0000000..4ec438a
--- /dev/null
@@ -0,0 +1,83 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Ecore_Js.hh>
+
+namespace efl { namespace ecore { namespace js {
+
+static Ecore_Job* extract_job(v8::Local<v8::Object> object)
+{
+    auto ptr = v8::External::Cast(*object->GetInternalField(0))->Value();
+    return reinterpret_cast<Ecore_Job*>(ptr);
+}
+
+static v8::Local<v8::Object> wrap_job(Ecore_Job *job, v8::Isolate *isolate)
+{
+    using v8::Boolean;
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_job_del(extract_job(info.This()));
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    ret->SetInternalField(0, compatibility_new<v8::External>(isolate, job));
+
+    return ret;
+}
+
+EAPI
+void register_job_add(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                      v8::Handle<v8::String> name)
+{
+    using v8::Local;
+    using v8::Value;
+    using v8::Undefined;
+    using v8::Function;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto f = new efl::eina::js::global_ref<Value>(args.GetIsolate(), args[0]);
+        auto ret = ecore_job_add([](void *data) {
+                auto persistent = static_cast<efl::eina::js::global_ref<Value>*>(data);
+               auto o = persistent->handle();
+
+                Function::Cast(*o)->Call(o->ToObject(), 0, NULL);
+
+                persistent->dispose();
+                delete persistent;
+            }, f);
+
+        return compatibility_return(wrap_job(ret, args.GetIsolate()), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_ecore_job(v8::Isolate *isolate,v8::Handle<v8::Object> exports)
+{
+   register_job_add(isolate, exports,
+                    compatibility_new<v8::String>(isolate, "ecore_job_add"));
+}
+      
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/ecore_js/ecore_js_mainloop.cc b/src/bindings/js/ecore_js/ecore_js_mainloop.cc
new file mode 100644 (file)
index 0000000..180b35f
--- /dev/null
@@ -0,0 +1,207 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Ecore_Js.hh>
+
+namespace efl { namespace ecore { namespace js {
+
+namespace {
+      
+void register_callback_cancel(v8::Isolate *isolate,
+                              v8::Handle<v8::Object> global,
+                              v8::Handle<v8::String> name)
+{
+    using v8::Boolean;
+    global->Set(name, compatibility_new<Boolean>(isolate,
+                                                 bool{ECORE_CALLBACK_CANCEL}));
+}
+
+void register_callback_renew(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name)
+{
+    using v8::Boolean;
+    global->Set(name, compatibility_new<Boolean>(isolate,
+                                                 bool{ECORE_CALLBACK_RENEW}));
+}
+
+void register_callback_pass_on(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Boolean;
+    global->Set(name, compatibility_new<Boolean>(isolate,
+                                                 bool{ECORE_CALLBACK_PASS_ON}));
+}
+
+void register_callback_done(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                            v8::Handle<v8::String> name)
+{
+    using v8::Boolean;
+    global->Set(name, compatibility_new<Boolean>(isolate,
+                                                 bool{ECORE_CALLBACK_DONE}));
+}
+
+void register_mainloop_iterate(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        ecore_main_loop_iterate();
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_mainloop_iterate_may_block(v8::Isolate *isolate,
+                                         v8::Handle<v8::Object> global,
+                                         v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        auto ret = ecore_main_loop_iterate_may_block(args[0]->NumberValue());
+        return compatibility_return(compatibility_new<Integer>
+                                    (args.GetIsolate(), ret), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_mainloop_begin(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        ecore_main_loop_begin();
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_mainloop_quit(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                            v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        ecore_main_loop_quit();
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_mainloop_animator_ticked_get(v8::Isolate *isolate,
+                                           v8::Handle<v8::Object> global,
+                                           v8::Handle<v8::String> name)
+{
+    using v8::Boolean;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto ret = ecore_main_loop_animator_ticked_get();
+        return compatibility_return(compatibility_new<Boolean>
+                                    (args.GetIsolate(), ret), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_mainloop_nested_get(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name)
+{
+    using v8::Boolean;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto ret = ecore_main_loop_nested_get();
+        return compatibility_return(compatibility_new<Boolean>
+                                    (args.GetIsolate(), ret), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+}
+      
+EAPI
+void register_ecore_mainloop(v8::Isolate *isolate,v8::Handle<v8::Object> exports)
+{
+   register_callback_cancel(isolate, exports,
+                            compatibility_new<v8::String>
+                            (isolate, "ECORE_CALLBACK_CANCEL"));
+   register_callback_renew(isolate, exports,
+                           compatibility_new<v8::String>
+                           (isolate, "ECORE_CALLBACK_RENEW"));
+   register_callback_pass_on(isolate, exports,
+                             compatibility_new<v8::String>
+                             (isolate, "ECORE_CALLBACK_PASS_ON"));
+   register_callback_done(isolate, exports,
+                          compatibility_new<v8::String>
+                          (isolate, "ECORE_CALLBACK_DONE"));
+   register_mainloop_iterate(isolate, exports,
+                             compatibility_new<v8::String>
+                             (isolate, "ecore_mainloop_iterate"));
+   register_mainloop_iterate_may_block(isolate, exports,
+                                       compatibility_new<v8::String>
+                                       (isolate,
+                                        "ecore_mainloop_iterate_may_block"));
+   register_mainloop_begin(isolate, exports,
+                           compatibility_new<v8::String>
+                           (isolate, "ecore_mainloop_begin"));
+   register_mainloop_quit(isolate, exports,
+                          compatibility_new<v8::String>
+                          (isolate, "ecore_mainloop_quit"));
+   register_mainloop_animator_ticked_get(isolate, exports,
+                                         compatibility_new<v8::String>
+                                         (isolate,
+                                          "ecore_mainlop_animator_ticked_get"));
+   register_mainloop_nested_get(isolate, exports,
+                                compatibility_new<v8::String>
+                                (isolate, "ecore_mainloop_nested_get"));
+}
+  
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/ecore_js/ecore_js_poller.cc b/src/bindings/js/ecore_js/ecore_js_poller.cc
new file mode 100644 (file)
index 0000000..e3bfbc8
--- /dev/null
@@ -0,0 +1,190 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Ecore_Js.hh>
+
+namespace efl { namespace ecore { namespace js {
+
+namespace {
+      
+Ecore_Poller* extract_poller(v8::Local<v8::Object> object)
+{
+    auto ptr = v8::External::Cast(*object->GetInternalField(0))->Value();
+    return reinterpret_cast<Ecore_Poller*>(ptr);
+}
+
+v8::Local<v8::Object> wrap_poller(Ecore_Poller *poller,
+                                         v8::Isolate *isolate)
+{
+    using v8::Boolean;
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_poller_del(extract_poller(info.This()));
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    ret->SetInternalField(0, compatibility_new<v8::External>(isolate, poller));
+
+    return ret;
+}
+
+void register_poller_core(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                          v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+
+    global->Set(name, compatibility_new<Integer>(isolate, ECORE_POLLER_CORE));
+}
+
+void register_poller_poll_interval_set(v8::Isolate *isolate,
+                                       v8::Handle<v8::Object> global,
+                                       v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 2 || !args[0]->IsNumber() || !args[1]->IsNumber())
+            return compatibility_return();
+
+        Ecore_Poller_Type type;
+
+        switch ((int)(args[0]->NumberValue())) {
+        case ECORE_POLLER_CORE:
+            type = ECORE_POLLER_CORE;
+            break;
+        default:
+            return compatibility_return();
+        }
+
+        ecore_poller_poll_interval_set(type, args[1]->NumberValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_poller_poll_interval_get(v8::Isolate *isolate,
+                                       v8::Handle<v8::Object> global,
+                                       v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        Ecore_Poller_Type type;
+
+        switch ((int)(args[0]->NumberValue())) {
+        case ECORE_POLLER_CORE:
+            type = ECORE_POLLER_CORE;
+            break;
+        default:
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_poller_poll_interval_get(type);
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_poller_add(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                         v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::Value;
+    using v8::FunctionTemplate;
+    using v8::Isolate;
+    using v8::Function;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 3 || !args[0]->IsNumber() || !args[1]->IsNumber()
+            || !args[2]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        Ecore_Poller_Type type;
+
+        switch ((int)(args[0]->NumberValue())) {
+        case ECORE_POLLER_CORE:
+            type = ECORE_POLLER_CORE;
+            break;
+        default:
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+        auto f = new efl::eina::js::global_ref<Value>(isolate, args[2]);
+
+        auto cb = [](void *data) -> Eina_Bool {
+            auto persistent = static_cast<efl::eina::js::global_ref<Value>*>(data);
+            auto o = persistent->handle();
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 0, NULL);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            if (!bret)
+              {
+                 persistent->dispose();
+                 delete persistent;
+              }
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto ret = ecore_poller_add(type, args[1]->NumberValue(), cb, f);
+        return compatibility_return(wrap_poller(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+}
+
+EAPI
+void register_ecore_poller(v8::Isolate *isolate,v8::Handle<v8::Object> exports)
+{
+   register_poller_core(isolate, exports,
+                        compatibility_new<v8::String>(isolate, "ECORE_POLLER_CORE"));
+   register_poller_poll_interval_set(isolate, exports,
+                                     compatibility_new<v8::String>(isolate,
+                                                               "ecore_poller"
+                                                               "_poll_interval"
+                                                               "_set"));
+   register_poller_poll_interval_get(isolate, exports,
+                                     compatibility_new<v8::String>(isolate,
+                                                               "ecore_poller"
+                                                               "_poll_interval"
+                                                               "_get"));
+   register_poller_add(isolate, exports,
+                       compatibility_new<v8::String>(isolate, "ecore_poller_add"));
+}
+  
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/ecore_js/ecore_js_throttle.cc b/src/bindings/js/ecore_js/ecore_js_throttle.cc
new file mode 100644 (file)
index 0000000..830a40f
--- /dev/null
@@ -0,0 +1,63 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Ecore_Js.hh>
+
+namespace efl { namespace ecore { namespace js {
+
+namespace {
+
+void register_throttle_adjust(v8::Isolate *isolate,
+                              v8::Handle<v8::Object> global,
+                              v8::Handle<v8::String> name)
+{
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        ecore_throttle_adjust(args[0]->NumberValue());
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_throttle_get(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                           v8::Handle<v8::String> name)
+{
+    using v8::Number;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ecore_throttle_get();
+        return compatibility_return(compatibility_new<Number>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+}
+      
+EAPI
+void register_ecore_throttle(v8::Isolate *isolate,v8::Handle<v8::Object> exports)
+{
+   register_throttle_adjust(isolate, exports,
+                            compatibility_new<v8::String>(isolate,
+                                                      "ecore_throttle_adjust"));
+   register_throttle_get(isolate, exports,
+                         compatibility_new<v8::String>(isolate,
+                                                   "ecore_throttle_get"));
+}
+      
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/ecore_js/ecore_js_timer.cc b/src/bindings/js/ecore_js/ecore_js_timer.cc
new file mode 100644 (file)
index 0000000..f22100c
--- /dev/null
@@ -0,0 +1,232 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Ecore_Js.hh>
+
+#include <memory>
+#include <cstdlib>
+
+namespace efl { namespace ecore { namespace js {
+
+namespace {
+
+Ecore_Timer* extract_timer(v8::Local<v8::Object> object)
+{
+    auto ptr = v8::External::Cast(*object->GetInternalField(0))->Value();
+    return reinterpret_cast<Ecore_Timer*>(ptr);
+}
+
+v8::Local<v8::Object> wrap_timer(Ecore_Timer *timer,
+                                 v8::Isolate *isolate)
+{
+    using v8::Boolean;
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_timer_del(extract_timer(info.This()));
+        return compatibility_return();
+    };
+
+    auto freeze = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_timer_freeze(extract_timer(info.This()));
+        return compatibility_return();
+    };
+
+    auto freeze_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto ret = ecore_timer_freeze_get(extract_timer(info.This()));
+        return compatibility_return(compatibility_new<Boolean>
+                                    (info.GetIsolate(), bool(ret)),
+                                    info);
+    };
+
+    auto thaw = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ecore_timer_thaw(extract_timer(info.This()));
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "freeze"),
+             compatibility_new<FunctionTemplate>(isolate, freeze)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "freeze_get"),
+             compatibility_new<FunctionTemplate>(isolate, freeze_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "thaw"),
+             compatibility_new<FunctionTemplate>(isolate, thaw)->GetFunction());
+
+    ret->SetInternalField(0, compatibility_new<v8::External>(isolate, timer));
+
+    return ret;
+}
+
+void register_timer_precision_get(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name)
+{
+    using v8::Number;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto ret = ecore_timer_precision_get();
+        return compatibility_return(compatibility_new<Number>
+                                    (args.GetIsolate(), ret), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_timer_precision_set(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name)
+{
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        ecore_timer_precision_set(args[0]->NumberValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_timer_add(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                        v8::Handle<v8::String> name)
+{
+    using v8::Local;
+    using v8::Value;
+    using v8::Undefined;
+    using v8::Function;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 2 || !args[0]->IsNumber()
+            || !args[1]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto f = new efl::eina::js::global_ref<Value>(args.GetIsolate(), args[1]);
+
+        auto cb = [](void *data) -> Eina_Bool {
+            auto persistent = reinterpret_cast<efl::eina::js::global_ref<Value>*>(data);
+            auto o = persistent->handle();
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 0, NULL);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            if (!bret)
+              {
+                 persistent->dispose();
+                 delete persistent;
+              }
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto ret = ecore_timer_add(args[0]->NumberValue(), cb, f);
+        return compatibility_return(wrap_timer(ret, args.GetIsolate()), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_timer_loop_add(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name)
+{
+    using v8::Local;
+    using v8::Value;
+    using v8::Undefined;
+    using v8::Function;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 2 || !args[0]->IsNumber()
+            || !args[1]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto f = new efl::eina::js::global_ref<Value>(args.GetIsolate(), args[1]);
+
+        auto cb = [](void *d) -> Eina_Bool {
+            auto persistent = static_cast<efl::eina::js::global_ref<Value>*>(d);
+            auto o = persistent->handle();
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 0, NULL);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            if (!bret)
+              {
+                 persistent->dispose();
+                 delete persistent;
+              }
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto ret = ecore_timer_loop_add(args[0]->NumberValue(), cb, f);
+
+        return compatibility_return(wrap_timer(ret, args.GetIsolate()), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+}
+
+EAPI
+void register_ecore_timer(v8::Isolate *isolate,v8::Handle<v8::Object> exports)
+{
+   register_timer_precision_get(isolate, exports,
+                                compatibility_new<v8::String>(isolate,
+                                                          "ecore_timer_precision"
+                                                          "_get"));
+   register_timer_precision_set(isolate, exports,
+                                compatibility_new<v8::String>(isolate,
+                                                          "ecore_timer_precision"
+                                                          "_set"));
+   register_timer_add(isolate, exports,
+                      compatibility_new<v8::String>(isolate, "ecore_timer_add"));
+   register_timer_loop_add(isolate, exports,
+                           compatibility_new<v8::String>(isolate,
+                                                     "ecore_timer_loop_add"));
+}
+
+} } } // namespace efl { namespace ecore { namespace js {
diff --git a/src/bindings/js/ecore_js/ecore_js_timer.hh b/src/bindings/js/ecore_js/ecore_js_timer.hh
new file mode 100644 (file)
index 0000000..e002587
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef ECORE_JS_TIMER_HH
+#define ECORE_JS_TIMER_HH
+
+#include <Eina.hh>
+
+#include <Eina_Js.hh>
+
+namespace efl { namespace ecore { namespace js {
+
+using ::efl::eina::js::compatibility_new;
+using ::efl::eina::js::compatibility_return_type;
+using ::efl::eina::js::compatibility_callback_info_type;
+using ::efl::eina::js::compatibility_return;
+using ::efl::eina::js::compatibility_get_pointer_internal_field;
+using ::efl::eina::js::compatibility_set_pointer_internal_field;
+using ::efl::eina::js::compatibility_persistent;
+
+void register_timer_precision_get(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name);
+
+void register_timer_precision_set(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name);
+
+void register_timer_dump(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                         v8::Handle<v8::String> name);
+
+void register_timer_add(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                        v8::Handle<v8::String> name);
+
+void register_timer_loop_add(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name);
+
+} } } // namespace efl::js
+
+#endif /* ECORE_JS_TIMER_HH */
diff --git a/src/bindings/js/efl_js/Efl_Js.hh b/src/bindings/js/efl_js/Efl_Js.hh
new file mode 100644 (file)
index 0000000..f494b38
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef EFL_EFL_JS_HH
+#define EFL_EFL_JS_HH
+
+#include <Eina.hh>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+#  define EAPI __declspec(dllexport)
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+namespace efl_js {
+
+EAPI void init(v8::Handle<v8::Object> exports);
+
+}
+
+#endif
diff --git a/src/bindings/js/efl_js/efl_js.cc b/src/bindings/js/efl_js/efl_js.cc
new file mode 100644 (file)
index 0000000..5665559
--- /dev/null
@@ -0,0 +1,241 @@
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Efl.h>
+#include <Efl_Config.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Eina.hh>
+#include <Eina_Js.hh>
+#include <Ecore_Js.hh>
+#include <Eio_Js.hh>
+#include <Eldbus_Js.hh>
+#include <Ethumb_Js.hh>
+
+#include <iostream>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+#  define EAPI __declspec(dllexport)
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+EAPI void eina_container_register(v8::Handle<v8::Object>, v8::Isolate* isolate);
+EAPI void eina_log_register(v8::Handle<v8::Object>, v8::Isolate* isolate);
+EAPI void eina_value_register(v8::Handle<v8::Object>, v8::Isolate* isolate);
+EAPI void register_ecore_mainloop(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+
+namespace ecore {
+EAPI void register_exe(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_idler(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_ecore(v8::Isolate* isolate, v8::Handle<v8::Object> exports);
+namespace idle {
+EAPI void register_enterer(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_exiter(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+}
+EAPI void register_job(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_parent(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_poller(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_timer(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+namespace con {
+EAPI void register_base(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_client(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_connector(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_server(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+}
+}
+
+namespace efl { namespace network {
+EAPI void register_url(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+}}
+
+EAPI void register_ecore_audio(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_ecore_audio_in(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_ecore_audio_in_sndfile(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_ecore_audio_in_tone(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_ecore_audio_out(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_ecore_audio_out_pulse(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_ecore_audio_out_sndfile(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+
+namespace efl {
+EAPI void register_control(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_file(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_image(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_player(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_text(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_text_properties(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+}
+
+namespace eo {
+EAPI void register_abstract_class(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_base(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+}
+
+namespace evas {
+EAPI void register_box(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_canvas(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_clickable_interface(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_common_interface(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_draggable_interface(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_grid(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_image(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_line(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_object(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_object_smart(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_out(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_polygon(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_rectangle(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_scrollable_interface(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_selectable_interface(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_signal_interface(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_smart_clipped(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_table(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_text(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_textblock(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_textgrid(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_zoomable_interface(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+
+namespace canvas3d {
+EAPI void register_camera(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_light(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_material(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_mesh(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_node(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_object(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_scene(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_texture(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+} }
+
+namespace edje {
+EAPI void register_edit(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+EAPI void register_object(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+}
+
+namespace emotion {
+EAPI void register_object(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+}
+
+#ifdef HAVE_NODEJS
+
+#include <eina_js_node.hh>
+
+namespace {
+#else
+namespace efl_js {
+#endif
+
+EAPI void init(v8::Handle<v8::Object> exports)
+{
+   ::eina_init();
+   ::ecore_init();
+   ::ecore_file_init();
+   ::ecore_evas_init();
+   ::eo_init();
+   ::eio_init();
+   ::evas_init();
+   try
+     {
+        eina_container_register(exports, v8::Isolate::GetCurrent());
+        eina_log_register(exports, v8::Isolate::GetCurrent());
+        eina_value_register(exports, v8::Isolate::GetCurrent());
+        register_ecore_mainloop(exports, v8::Isolate::GetCurrent());
+        efl::ecore::js::register_ecore(v8::Isolate::GetCurrent(), exports);
+        efl::eio::js::register_eio(v8::Isolate::GetCurrent(), exports);
+        efl::eldbus::js::register_eldbus(v8::Isolate::GetCurrent(), exports);
+        efl::ethumb::js::register_ethumb(v8::Isolate::GetCurrent(), exports);
+        ecore::register_exe(exports, v8::Isolate::GetCurrent());
+        ecore::register_idler(exports, v8::Isolate::GetCurrent());
+        ecore::idle::register_enterer(exports, v8::Isolate::GetCurrent());
+        ecore::idle::register_exiter(exports, v8::Isolate::GetCurrent());
+        ecore::register_job(exports, v8::Isolate::GetCurrent());
+        ecore::register_parent(exports, v8::Isolate::GetCurrent());
+        ecore::register_poller(exports, v8::Isolate::GetCurrent());
+        ecore::register_timer(exports, v8::Isolate::GetCurrent());
+        ecore::con::register_base(exports, v8::Isolate::GetCurrent());
+        ecore::con::register_client(exports, v8::Isolate::GetCurrent());
+        ecore::con::register_connector(exports, v8::Isolate::GetCurrent());
+        ecore::con::register_server(exports, v8::Isolate::GetCurrent());
+        efl::network::register_url(exports, v8::Isolate::GetCurrent());
+#if 1
+        register_ecore_audio(exports, v8::Isolate::GetCurrent());
+        register_ecore_audio_in(exports, v8::Isolate::GetCurrent());
+        register_ecore_audio_in_sndfile(exports, v8::Isolate::GetCurrent());
+        register_ecore_audio_in_tone(exports, v8::Isolate::GetCurrent());
+        register_ecore_audio_out(exports, v8::Isolate::GetCurrent());
+        register_ecore_audio_out_pulse(exports, v8::Isolate::GetCurrent());
+        register_ecore_audio_out_sndfile(exports, v8::Isolate::GetCurrent());
+#endif
+        efl::register_control(exports, v8::Isolate::GetCurrent());
+        efl::register_file(exports, v8::Isolate::GetCurrent());
+        efl::register_image(exports, v8::Isolate::GetCurrent());
+        efl::register_player(exports, v8::Isolate::GetCurrent());
+        efl::register_text(exports, v8::Isolate::GetCurrent());
+        efl::register_text_properties(exports, v8::Isolate::GetCurrent());
+        eo::register_abstract_class(exports, v8::Isolate::GetCurrent());
+        eo::register_base(exports, v8::Isolate::GetCurrent());
+#if 1
+        evas::register_box(exports, v8::Isolate::GetCurrent());
+        evas::register_canvas(exports, v8::Isolate::GetCurrent());
+        evas::register_clickable_interface(exports, v8::Isolate::GetCurrent());
+        evas::register_common_interface(exports, v8::Isolate::GetCurrent());
+        evas::register_draggable_interface(exports, v8::Isolate::GetCurrent());
+        evas::register_grid(exports, v8::Isolate::GetCurrent());
+        evas::register_image(exports, v8::Isolate::GetCurrent());
+        evas::register_line(exports, v8::Isolate::GetCurrent());
+        evas::register_object(exports, v8::Isolate::GetCurrent());
+        evas::register_object_smart(exports, v8::Isolate::GetCurrent());
+        evas::register_out(exports, v8::Isolate::GetCurrent());
+        evas::register_polygon(exports, v8::Isolate::GetCurrent());
+        evas::register_rectangle(exports, v8::Isolate::GetCurrent());
+        evas::register_scrollable_interface(exports, v8::Isolate::GetCurrent());
+        evas::register_selectable_interface(exports, v8::Isolate::GetCurrent());
+        evas::register_signal_interface(exports, v8::Isolate::GetCurrent());
+        evas::register_smart_clipped(exports, v8::Isolate::GetCurrent());
+        evas::register_table(exports, v8::Isolate::GetCurrent());
+        evas::register_text(exports, v8::Isolate::GetCurrent());
+        evas::register_textblock(exports, v8::Isolate::GetCurrent());
+        evas::register_textgrid(exports, v8::Isolate::GetCurrent());
+        evas::register_zoomable_interface(exports, v8::Isolate::GetCurrent());
+        evas::canvas3d::register_camera(exports, v8::Isolate::GetCurrent());
+        evas::canvas3d::register_light(exports, v8::Isolate::GetCurrent());
+        evas::canvas3d::register_material(exports, v8::Isolate::GetCurrent());
+        evas::canvas3d::register_mesh(exports, v8::Isolate::GetCurrent());
+        evas::canvas3d::register_node(exports, v8::Isolate::GetCurrent());
+        evas::canvas3d::register_object(exports, v8::Isolate::GetCurrent());
+        evas::canvas3d::register_scene(exports, v8::Isolate::GetCurrent());
+        evas::canvas3d::register_texture(exports, v8::Isolate::GetCurrent());
+#endif
+#if 1
+        edje::register_edit(exports, v8::Isolate::GetCurrent());
+        edje::register_object(exports, v8::Isolate::GetCurrent());
+#endif
+#if 1
+        emotion::register_object(exports, v8::Isolate::GetCurrent());
+#endif
+     }
+   catch(...)
+     {
+        std::cout << "Exception" << std::endl;
+     }
+}
+
+#ifdef HAVE_NODEJS
+}
+NODE_MODULE(efl, init)
+#else
+} // namespace efl
+#endif
diff --git a/src/bindings/js/eina_js/Eina_Js.hh b/src/bindings/js/eina_js/Eina_Js.hh
new file mode 100644 (file)
index 0000000..b193b54
--- /dev/null
@@ -0,0 +1,50 @@
+
+#ifndef EFL_EINA_JS_HH
+#define EFL_EINA_JS_HH
+
+#include <Eina.hh>
+#include <eo_concrete.hh>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_EINA_JS_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+#include <eina_js_container.hh>
+#include <eina_js_accessor.hh>
+#include <eina_js_array.hh>
+#include <eina_js_compatibility.hh>
+#include <eina_js_error.hh>
+#include <eina_js_get_value_from_c.hh>
+#include <eina_js_get_value.hh>
+#include <eina_js_iterator.hh>
+#include <eina_js_list.hh>
+#include <eina_js_log.hh>
+#include <eina_js_value.hh>
+#include <eina_js_log.hh>
+
+#undef EAPI
+#define EAPI
+
+#endif
diff --git a/src/bindings/js/eina_js/eina_js_accessor.cc b/src/bindings/js/eina_js/eina_js_accessor.cc
new file mode 100644 (file)
index 0000000..d689154
--- /dev/null
@@ -0,0 +1,34 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eina.hh>
+
+#include <Eina_Js.hh>
+
+#include <iostream>
+
+namespace efl { namespace eina { namespace js {
+
+EAPI void register_destroy_accessor(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name)
+{
+    typedef void (*deleter_t)(void*);
+
+    auto f = [](compatibility_callback_info_type info) -> compatibility_return_type
+      {
+        if (info.Length() != 1 || !info[0]->IsObject())
+          return compatibility_return();
+
+        v8::Handle<v8::Object> o = info[0]->ToObject();
+
+        deleter_t deleter = compatibility_get_pointer_internal_field<deleter_t>(o, 1);
+        deleter(compatibility_get_pointer_internal_field<>(o, 0));
+        return compatibility_return();
+      };
+
+    global->Set(name, compatibility_new<v8::FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/eina_js/eina_js_accessor.hh b/src/bindings/js/eina_js/eina_js_accessor.hh
new file mode 100644 (file)
index 0000000..abf3090
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef EINA_JS_ACCESSOR_HH
+#define EINA_JS_ACCESSOR_HH
+
+#include <memory>
+
+#include <eina_js_value.hh>
+#include <eina_js_compatibility.hh>
+#include <eina_js_get_value.hh>
+#include <eina_js_get_value_from_c.hh>
+
+#include <iostream>
+
+namespace efl { namespace eina { namespace js {
+
+template <typename T, typename A>
+js::compatibility_return_type accessor_get(js::compatibility_callback_info_type info)
+{
+  v8::Isolate* isolate = info.GetIsolate();
+  if (info.Length() != 1 || !info[0]->IsNumber())
+    return js::compatibility_return();
+
+  auto idx = js::get_value_from_javascript
+    (info[0], isolate, "", js::value_tag<std::size_t>());
+
+  std::string class_name;
+  if (info.Data()->IsString())
+    {
+       v8::String::Utf8Value str(info.Data());
+       class_name = *str;
+    }
+
+  void *ptr = compatibility_get_pointer_internal_field(info.Holder(), 0);
+
+  return compatibility_return
+    (::efl::eina::js::get_value_from_c
+      (js::wrap_value<T>(container_unwrap((*static_cast<A*>(ptr))[idx]), js::value_tag<T>{})
+                         , isolate, class_name.c_str()), info);
+};
+
+/* Creates a copy from \p a accessor and exports it to be manipulated by the JS
+   code */
+template <typename T, typename W>
+inline v8::Local<v8::Object> export_accessor(::efl::eina::accessor<W> &a, v8::Isolate *isolate, const char* class_name)
+{
+  typedef ::efl::eina::accessor<W> accessor_type;
+
+  static efl::eina::js::global_ref<v8::ObjectTemplate> obj_tpl
+    (isolate, 
+    [&]() 
+    {
+      auto obj_tpl = compatibility_new<v8::ObjectTemplate>(isolate);
+      (*obj_tpl)->SetInternalFieldCount(1);
+
+      // TODO: (*obj_tpl)->SetIndexedPropertyHandler(&accessor_get<accessor_type>);
+
+      (*obj_tpl)->Set(js::compatibility_new<v8::String>(isolate, "get")
+                      , js::compatibility_new<v8::FunctionTemplate>(isolate
+                                                                    , &accessor_get<T, accessor_type>
+                                                                    , js::compatibility_new<v8::String>(isolate, class_name)));
+      return obj_tpl;
+    }());
+
+  auto instance = obj_tpl.handle()->NewInstance();
+  compatibility_set_pointer_internal_field(instance, 0, &a);
+  return instance;
+}
+
+/* Extracts and returns a copy from the internal accessor object from the JS
+   object */
+template <typename T>
+::efl::eina::accessor<T>& import_accessor(v8::Handle<v8::Object> o)
+{
+  typedef ::efl::eina::accessor<T> accessor_type;
+
+  void* ptr = compatibility_get_pointer_internal_field(o, 0);
+  
+  return *static_cast<accessor_type*>(ptr);
+}
+
+/* Registers the function to destroy the accessor objects to the JS code */
+void register_destroy_accessor(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name);
+
+} } } // namespace efl::js
+
+#endif /* EINA_JS_ACCESSOR_HH */
diff --git a/src/bindings/js/eina_js/eina_js_array.hh b/src/bindings/js/eina_js/eina_js_array.hh
new file mode 100644 (file)
index 0000000..9cdd142
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef EINA_JS_ARRAY_HH
+#define EINA_JS_ARRAY_HH
+
+#include <iostream>
+
+#include <iterator>
+
+#include <eina_js_container.hh>
+
+namespace efl { namespace eina { namespace js {
+    
+template <typename T, typename K, typename W>
+struct eina_array : eina_container_common<efl::eina::array
+                                    <W
+                                    , typename std::conditional
+                                      <std::is_base_of<efl::eo::concrete, W>::value
+                                       , efl::eina::eo_clone_allocator
+                                       , efl::eina::malloc_clone_allocator
+                                       >::type>, T, K>
+{
+  typedef eina_container_common<efl::eina::array<W
+                           , typename std::conditional
+                           <std::is_base_of<efl::eo::concrete, W>::value
+                            , efl::eina::eo_clone_allocator
+                            , efl::eina::malloc_clone_allocator
+                            >::type>, T, K> base_type;
+  using base_type::base_type;
+  typedef typename base_type::container_type container_type;
+
+  eina_container_base* concat(eina_container_base const& other) const
+  {
+    return detail::concat(*this, other);
+  }
+  eina_container_base* slice(std::int64_t i, std::int64_t j) const
+  {
+    return detail::slice(*this, i, j);
+  }
+  v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t index, v8::Local<v8::Value> v)
+  {
+    return detail::set<T,W>(isolate, *this, index, v);
+  }
+  int push(v8::Isolate* isolate, v8::Local<v8::Value> v)
+  {
+    return detail::push<T,W>(isolate, *this, v);
+  }
+  v8::Local<v8::Value> pop(v8::Isolate* isolate)
+  {
+    return detail::pop<T,W,K>(isolate, *this);
+  }
+  js::container_type get_container_type() const { return array_container_type; }
+};
+
+template <typename T, typename K, typename W>
+struct range_eina_array : eina_container_common<efl::eina::range_array<W>, T, K>
+{
+  typedef eina_container_common<efl::eina::range_array<W>, T, K> base_type;
+  using base_type::base_type;
+  typedef typename base_type::container_type container_type;
+  typedef typename std::conditional
+    <std::is_base_of<efl::eo::concrete, W>::value
+     , efl::eina::eo_clone_allocator
+     , efl::eina::malloc_clone_allocator
+     >::type clone_allocator_type;
+  
+  eina_container_base* concat(eina_container_base const& other) const
+  {
+    range_eina_array<T, K, W> const& rhs = static_cast<range_eina_array<T, K, W>const&>(other);
+    efl::eina::array<W, clone_allocator_type>
+      array(this->_container.begin(), this->_container.end());
+    array.insert(array.end(), rhs._container.begin(), rhs._container.end());
+    return new eina_array<T, K, W>(array.release_native_handle());
+  }
+  eina_container_base* slice(std::int64_t i, std::int64_t j) const
+  {
+    efl::eina::array<W, clone_allocator_type>
+      array(std::next(this->_container.begin(), i), std::next(this->_container.begin(), j));
+    return new eina_array<T, K, W>(array.release_native_handle());
+  }
+  js::container_type get_container_type() const { return array_container_type; }
+};
+
+// Problematic types.
+template <>
+struct eina_array<_Elm_Calendar_Mark*, js::nonclass_cls_name_getter, _Elm_Calendar_Mark>
+  : empty_container_base
+{ eina_array(Eina_Array const*){} };
+template <>
+struct eina_array<Elm_Gen_Item*, js::nonclass_cls_name_getter, Elm_Gen_Item>
+  : empty_container_base
+{ eina_array(Eina_Array const*){} };
+template <>
+struct eina_array<_Evas_Textblock_Rectangle*, js::nonclass_cls_name_getter, _Evas_Textblock_Rectangle>
+  : empty_container_base
+{ eina_array(Eina_Array const*){} };
+template <>
+struct eina_array<_Elm_Map_Overlay*, js::nonclass_cls_name_getter, _Elm_Map_Overlay>
+  : empty_container_base
+{ eina_array(Eina_Array const*){} };
+
+template <>
+struct range_eina_array<_Elm_Calendar_Mark*, js::nonclass_cls_name_getter, _Elm_Calendar_Mark>
+  : empty_container_base
+{ range_eina_array(Eina_Array const*){} };
+template <>
+struct range_eina_array<Elm_Gen_Item*, js::nonclass_cls_name_getter, Elm_Gen_Item>
+  : empty_container_base
+{ range_eina_array(Eina_Array const*){} };
+template <>
+struct range_eina_array<_Evas_Textblock_Rectangle*, js::nonclass_cls_name_getter, _Evas_Textblock_Rectangle>
+  : empty_container_base
+{ range_eina_array(Eina_Array const*){} };
+template <>
+struct range_eina_array<_Elm_Map_Overlay*, js::nonclass_cls_name_getter, _Elm_Map_Overlay>
+  : empty_container_base
+{ range_eina_array(Eina_Array const*){} };
+
+} } }
+
+#endif
diff --git a/src/bindings/js/eina_js/eina_js_compatibility.cc b/src/bindings/js/eina_js/eina_js_compatibility.cc
new file mode 100644 (file)
index 0000000..a1d992f
--- /dev/null
@@ -0,0 +1,12 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eina.hh>
+#include <Eina_Js.hh>
+
+namespace efl { namespace eina { namespace js {
+
+std::map<std::string, v8::Local<v8::Function>> constructors_map_;
+
+} } }
diff --git a/src/bindings/js/eina_js/eina_js_compatibility.hh b/src/bindings/js/eina_js/eina_js_compatibility.hh
new file mode 100644 (file)
index 0000000..9ef0cb8
--- /dev/null
@@ -0,0 +1,918 @@
+#ifndef EFL_EINA_JS_COMPATIBILITY_HH
+#define EFL_EINA_JS_COMPATIBILITY_HH
+
+#include <type_traits>
+#include <utility>
+#include <map>
+#include <string>
+#include <cstdlib>
+
+
+#ifdef HAVE_NODE_V8_H
+#include <node/v8.h>
+#elif defined(HAVE_NODEJS_DEPS_V8_V8_H)
+#include <nodejs/deps/v8/v8.h>
+#elif defined(HAVE_NODEJS_DEPS_V8_INCLUDE_V8_H)
+#include <nodejs/deps/v8/include/v8.h>
+#elif defined(HAVE_NODEJS_SRC_V8_H)
+#include <nodejs/src/v8.h>
+#elif defined(HAVE_V8_H)
+#include <v8.h>
+#else
+#error We must have at least one v8 header to include
+#endif
+
+namespace v8 {
+
+template <typename T>
+struct FunctionCallbackInfo;
+template <typename T>
+struct PropertyCallbackInfo;
+template <typename T>
+#ifdef HAVE_V8_GLOBAL
+struct Global;
+#else
+struct UniquePersistent;
+#endif
+
+class AccessorInfo;
+
+class Arguments;
+
+}
+
+namespace efl { namespace eina { namespace js {
+
+template <typename T>
+struct value_tag
+{
+  typedef T type;
+};
+
+template <typename T, typename... U>
+struct complex_tag
+{
+  T value;
+  typedef std::tuple<U...> inner_types;
+};
+
+template <typename T>
+struct make_tag_traits
+{
+  typedef typename std::remove_reference<T>::type a1;
+  typedef typename std::conditional
+  <std::is_pointer<T>::value
+    , typename std::remove_cv<T>::type
+    , T>::type type;
+};
+      
+template <typename T, typename... U>
+using make_complex_tag = complex_tag<typename make_tag_traits<T>::type
+                                     , typename make_tag_traits<U>::type...>;
+
+template <typename T>
+struct struct_tag
+{
+  T value;
+};
+
+template <typename T>
+using make_struct_tag = struct_tag<typename make_tag_traits<T>::type>;
+      
+template <typename T>
+struct struct_ptr_tag
+{
+  T value;
+};
+
+template <typename T>
+using make_struct_ptr_tag = struct_ptr_tag<typename make_tag_traits<T>::type>;
+      
+template <typename T, typename... Ts>
+struct remove_tag
+{
+  typedef T type;
+};
+
+template <typename T, typename... U>
+struct remove_tag<complex_tag<T, U...>>
+{
+  typedef typename eina::js::remove_tag<T, U...>::type type;
+};
+
+template <typename T>
+struct remove_tag<struct_tag<T>>
+{
+  typedef typename eina::js::remove_tag<T>::type type;
+};
+
+template <typename T>
+struct remove_tag<struct_ptr_tag<T>>
+{
+  typedef typename eina::js::remove_tag<T>::type type;
+};
+
+template <typename T>
+struct is_handable_by_value
+{
+  static constexpr bool value = !std::is_class<T>::value || std::is_same<T, ::efl::eo::concrete>::value;
+};
+
+template <typename... T>
+struct container_wrapper
+{
+  typedef typename eina::js::remove_tag<T...>::type _notag_type;
+  typedef typename std::conditional<
+    std::is_convertible<_notag_type, Eo const* const>::value
+    , typename std::conditional<
+        std::is_const<typename std::remove_pointer<_notag_type>::type>::value
+        , ::efl::eo::concrete const
+        , ::efl::eo::concrete
+    >::type
+    , _notag_type
+  >::type type;
+};
+
+template <typename T>
+T container_wrap(T&& v)
+{
+  return std::forward<T>(v);
+}
+
+inline ::efl::eo::concrete container_wrap(Eo* v)
+{
+  if(v)
+    eo_ref(v);
+  return ::efl::eo::concrete{v};
+}
+
+inline ::efl::eo::concrete container_wrap(Eo const* v)
+{
+  if (v)
+    eo_ref(v);
+  return ::efl::eo::concrete{const_cast<Eo*>(v)};
+}
+
+template <typename T>
+T& container_unwrap(T& v)
+{
+  return v;
+}
+
+inline Eo* container_unwrap(::efl::eo::concrete& v)
+{
+  return v._eo_ptr();
+}
+
+inline Eo* container_unwrap(::efl::eo::concrete const& v)
+{
+  return v._eo_ptr();
+}
+
+template <typename T>
+struct is_complex_tag : std::false_type {};
+
+template <typename... T>
+struct is_complex_tag<complex_tag<T...>> : std::true_type {};
+
+template <typename T>
+struct is_struct_tag : std::false_type {};
+
+template <typename T>
+struct is_struct_tag<struct_tag<T>> : std::true_type {};
+
+template <typename T>
+struct is_struct_ptr_tag : std::false_type {};
+
+template <typename T>
+struct is_struct_ptr_tag<struct_ptr_tag<T>> : std::true_type {};
+
+template <typename T>
+struct is_type_tag
+{
+  static constexpr bool value =
+    is_complex_tag<T>::value
+    || is_struct_tag<T>::value
+    || is_struct_ptr_tag<T>::value;
+};
+
+
+// Class name getters
+struct cls_name_getter_base {};
+struct cls_name_getter_generated_base : cls_name_getter_base {};
+/// Name getter for types that are not classes
+struct nonclass_cls_name_getter : cls_name_getter_base
+{
+  static char const* class_name() { return ""; }
+};
+
+// JS container base
+enum container_type
+{
+  list_container_type
+  , array_container_type
+  , container_type_size
+};
+
+struct eina_container_base
+{
+  virtual ~eina_container_base() {}
+
+  virtual std::size_t size() const = 0;
+  virtual eina_container_base* concat(eina_container_base const& rhs) const = 0;
+  virtual eina_container_base* slice(std::int64_t i, std::int64_t j) const = 0;
+  virtual int index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const = 0;
+  virtual int last_index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const = 0;
+  virtual v8::Local<v8::Value> get(v8::Isolate*, std::size_t) const = 0;
+  virtual v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t index, v8::Local<v8::Value> v) = 0;
+  virtual int push(v8::Isolate* isolate, v8::Local<v8::Value> v) = 0;
+  virtual v8::Local<v8::Value> pop(v8::Isolate* isolate) = 0;
+  virtual v8::Local<v8::String> to_string(v8::Isolate*) const = 0;
+  virtual v8::Local<v8::String> join(v8::Isolate*, v8::Local<v8::Value> separator) const = 0;
+  virtual container_type get_container_type() const = 0;
+  virtual void* get_container_native_handle() = 0;
+  virtual void const* get_container_native_handle() const = 0;
+};
+
+// Containers forward declarations
+
+// Array
+template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
+struct eina_array;
+template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
+struct range_eina_array;
+
+EAPI v8::Handle<v8::Function> get_array_instance_template();
+
+// List
+template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
+struct eina_list;
+template <typename T, typename K = nonclass_cls_name_getter, typename W = typename container_wrapper<T>::type>
+struct range_eina_list;
+
+EAPI v8::Handle<v8::Function> get_list_instance_template();
+
+// Accessor
+template <typename T, typename W>
+v8::Local<v8::Object> export_accessor(::efl::eina::accessor<W>&, v8::Isolate*, const char*);
+
+template <typename T>
+::efl::eina::accessor<T>& import_accessor(v8::Handle<v8::Object>);
+
+// Wrap value functions
+template <typename R, typename T>
+typename std::remove_cv<typename std::remove_reference<R>::type>::type
+wrap_value(T v, value_tag<R>
+           , typename std::enable_if<!is_type_tag<typename std::remove_cv<R>::type>::value>::type* = 0)
+{
+   return v;
+}
+
+template <typename R, typename T>
+R wrap_value(T const& v, value_tag<eina::js::struct_tag<T>>)
+{
+   return R {v};
+}
+
+template <typename R, typename T>
+R wrap_value(T v, value_tag<eina::js::struct_ptr_tag<T>>)
+{
+   return R {v};
+}
+
+template <typename R, typename T, typename... U>
+R wrap_value(T v, value_tag<eina::js::complex_tag<T, U...>>)
+{
+   return R {v};
+}
+
+template <typename T = v8::External>
+struct _libv8_isolate_test
+{
+   using new_signature = v8::Local<T>(*)(v8::Isolate*, void*);
+   static const bool value = std::is_same<decltype(static_cast<new_signature>(&T::New)), new_signature>::value;
+};
+
+template <typename T = v8::FunctionTemplate, typename Enable = void>
+struct _libv8_callback_info_test;
+
+typedef v8::Handle<v8::Value>(*_libv8_invocation_callback)(v8::Arguments const&);
+
+template <typename T>
+struct _libv8_callback_info_test
+<T, typename std::enable_if
+ <!std::is_same<decltype( & T::SetCallHandler)
+   , void (T::*)(_libv8_invocation_callback, v8::Handle<v8::Value>)>::value>::type>
+  : std::true_type
+{
+};
+
+template <typename T>
+struct _libv8_callback_info_test
+<T, typename std::enable_if
+ <std::is_same<decltype( & T::SetCallHandler)
+   , void (T::*)(_libv8_invocation_callback, v8::Handle<v8::Value>)>::value>::type>
+  : std::false_type
+{
+};
+
+template <typename T = v8::ObjectTemplate, typename Enable = void>
+struct _libv8_property_callback_info_test
+  : std::true_type {};
+
+typedef v8::Handle<v8::Value>(*_libv8_getter_callback)(v8::Local<v8::String>, v8::AccessorInfo const&);
+typedef void(*_libv8_setter_callback)(v8::Local<v8::String>, v8::Local<v8::Value>, v8::AccessorInfo const&);
+
+template <typename T>
+struct _libv8_property_callback_info_test
+<T, typename std::enable_if
+ <std::is_same<decltype( & T::SetAccessor)
+   , void (T::*)
+     (v8::Handle<v8::String>
+      , _libv8_getter_callback
+      , _libv8_setter_callback
+      , v8::Handle<v8::Value>
+      , v8::AccessControl
+      , v8::PropertyAttribute
+      , v8::Handle<v8::AccessorSignature>
+      )>::value>::type>
+  : std::false_type
+{
+};
+
+static constexpr bool const v8_uses_isolate = _libv8_isolate_test<>::value;
+static constexpr bool const v8_uses_callback_info = _libv8_callback_info_test<>::value;
+static constexpr bool const v8_uses_property_callback_info = _libv8_property_callback_info_test<>::value;
+
+using compatibility_return_type = std::conditional<v8_uses_callback_info, void, v8::Handle<v8::Value> >::type;
+using compatibility_callback_info_type
+ = std::conditional<v8_uses_callback_info, v8::FunctionCallbackInfo<v8::Value> const&, v8::Arguments const&>
+  ::type;
+using compatibility_callback_info_pointer
+ = std::conditional<v8_uses_callback_info, v8::FunctionCallbackInfo<v8::Value> const*, v8::Arguments const*>
+  ::type;
+
+typedef compatibility_return_type(*compatibility_function_callback)(compatibility_callback_info_type);
+
+using compatibility_accessor_getter_return_type
+  = std::conditional<v8_uses_property_callback_info, void, v8::Handle<v8::Value> >::type;
+using compatibility_accessor_getter_callback_info_type
+ = std::conditional<v8_uses_property_callback_info
+                    , v8::PropertyCallbackInfo<v8::Value> const&, v8::AccessorInfo const&>
+  ::type;
+
+using compatibility_accessor_setter_return_type
+  = void;
+using compatibility_accessor_setter_callback_info_type
+ = std::conditional<v8_uses_property_callback_info
+                    , v8::PropertyCallbackInfo<void> const&, v8::AccessorInfo const&>
+  ::type;
+
+using compatibility_indexed_property_getset_return_type
+ = std::conditional<v8_uses_property_callback_info, void, v8::Handle<v8::Value> >::type;
+using compatibility_indexed_property_callback_info_type
+ = std::conditional<v8_uses_property_callback_info
+                    , v8::PropertyCallbackInfo<v8::Value> const&, v8::AccessorInfo const&>
+  ::type;
+
+static_assert(v8_uses_property_callback_info == v8_uses_callback_info
+              && v8_uses_callback_info == v8_uses_isolate, "");
+
+template <typename T>
+struct compatibility_type_tag {};
+
+template <bool = v8_uses_isolate>
+struct compatibility_string;
+
+template <>
+struct compatibility_string<true> : v8::String
+{
+  template <typename... Args>
+  static v8::Local<v8::String> New(Args...args)
+  {
+    return NewFromUtf8(v8::Isolate::GetCurrent(), args...);
+  }
+};
+
+template <>
+struct compatibility_string<false> : v8::String
+{
+};
+
+template <typename...Args>
+auto compatibility_new_impl(v8::Isolate*, std::true_type, compatibility_type_tag<v8::String>
+                            , Args...args) ->
+  decltype(compatibility_string<>::New(args...))
+{
+  return compatibility_string<>::New(args...);
+}
+
+template <typename...Args>
+auto compatibility_new_impl(v8::Isolate*, std::false_type, compatibility_type_tag<v8::String>
+                            , Args...args) ->
+  decltype(compatibility_string<>::New(args...))
+{
+  return compatibility_string<>::New(args...);
+}
+
+template <typename...Args>
+auto compatibility_new_impl(std::nullptr_t, std::true_type, compatibility_type_tag<v8::String>
+                            , Args...args) ->
+  decltype(compatibility_string<>::New(args...))
+{
+  return compatibility_string<>::New(args...);
+}
+
+template <typename...Args>
+auto compatibility_new_impl(std::nullptr_t, std::false_type, compatibility_type_tag<v8::String>
+                            , Args...args) ->
+  decltype(compatibility_string<>::New(args...))
+{
+  return compatibility_string<>::New(args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new_impl(v8::Isolate* isolate, std::true_type, compatibility_type_tag<T>
+                            , Args...args) ->
+  decltype(T::New(isolate, args...))
+{
+  return T::New(isolate, args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new_impl(v8::Isolate*, std::false_type, compatibility_type_tag<T>
+                            , Args...args) ->
+  decltype(T::New(args...))
+{
+  return T::New(args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new_impl(std::nullptr_t, std::true_type, compatibility_type_tag<T>
+                            , Args...args) ->
+  decltype(T::New(v8::Isolate::GetCurrent(), args...))
+{
+  return T::New(v8::Isolate::GetCurrent(), args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new_impl(std::nullptr_t, std::false_type, compatibility_type_tag<T>
+                            , Args...args) ->
+  decltype(T::New(args...))
+{
+  return T::New(args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new(v8::Isolate* isolate, Args...args) ->
+  decltype(js::compatibility_new_impl<>
+           (isolate, std::integral_constant<bool, v8_uses_isolate>()
+            , compatibility_type_tag<T>()
+            , args...))
+{
+  return js::compatibility_new_impl(isolate, std::integral_constant<bool, v8_uses_isolate>()
+                                    , compatibility_type_tag<T>()
+                                    , args...);
+}
+
+template <typename T, typename...Args>
+auto compatibility_new(std::nullptr_t, Args...args) ->
+  decltype(js::compatibility_new_impl<>(nullptr, std::integral_constant<bool, v8_uses_isolate>()
+                                        , compatibility_type_tag<T>()
+                                        , args...))
+{
+  return js::compatibility_new_impl<>(nullptr, std::integral_constant<bool, v8_uses_isolate>()
+                                      , compatibility_type_tag<T>()
+                                      , args...);
+}
+
+#ifdef HAVE_V8_CREATE_PARAMS
+namespace detail {
+class array_buffer_allocator : public v8::ArrayBuffer::Allocator
+{
+  public:
+  virtual void* Allocate(std::size_t length)
+  {
+    void* data = AllocateUninitialized(length);
+    return data ? std::memset(data, 0, length) : data;
+  }
+  virtual void* AllocateUninitialized(std::size_t length) { return std::malloc(length); }
+  virtual void Free(void* data, std::size_t) { std::free(data); }
+};
+}
+
+inline v8::Isolate* compatibility_isolate_new()
+{
+  static detail::array_buffer_allocator allocator;
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = &allocator;
+  return v8::Isolate::New(create_params);
+}
+
+#else
+
+inline v8::Isolate* compatibility_isolate_new()
+{
+  return v8::Isolate::New();
+}
+
+#endif
+
+template <typename T, typename U>
+inline void compatibility_return_impl(T object, U const& info, std::true_type)
+{
+  info.GetReturnValue().Set(object);
+}
+
+template <typename T>
+inline v8::Handle<v8::Value>
+compatibility_return_impl(T object, compatibility_callback_info_type, std::false_type)
+{
+  return object;
+}
+
+template <typename T>
+inline v8::Handle<v8::Value>
+compatibility_return_impl(T object, compatibility_accessor_getter_callback_info_type, std::false_type)
+{
+  return object;
+}
+
+template <typename T>
+compatibility_return_type
+compatibility_return(T object, compatibility_callback_info_type args)
+{
+  return compatibility_return_impl(object, args, std::integral_constant<bool, v8_uses_callback_info>());
+}
+
+template <typename T>
+compatibility_return_type
+compatibility_return(T object, compatibility_accessor_getter_callback_info_type args)
+{
+  return compatibility_return_impl(object, args, std::integral_constant<bool, v8_uses_property_callback_info>());
+}
+
+inline void compatibility_return_nil_impl(std::true_type) {}
+
+inline v8::Handle<v8::Value>
+compatibility_return_nil_impl(std::false_type)
+{
+  return v8::Handle<v8::Value>();
+}
+
+inline
+compatibility_return_type
+compatibility_return()
+{
+  return compatibility_return_nil_impl(std::integral_constant<bool, v8_uses_callback_info>());
+}
+
+struct _v8_isolate_throw_exception : v8::Isolate
+{
+  v8::Handle<v8::Value> ThrowException_impl(v8::Handle<v8::Value> v)
+  {
+    using namespace v8;
+    return ThrowException(v);
+  }
+};
+
+inline void
+compatibility_throw_impl(v8::Isolate* isolate, v8::Local<v8::Value> exception, std::true_type)
+{
+  static_cast<_v8_isolate_throw_exception*>(isolate)->ThrowException_impl(exception);
+}
+
+inline v8::Handle<v8::Value>
+compatibility_throw_impl(v8::Isolate* isolate, v8::Local<v8::Value> exception, std::false_type)
+{
+  return static_cast<_v8_isolate_throw_exception*>(isolate)->ThrowException_impl(exception);
+}
+
+inline std::conditional<v8_uses_isolate, void, v8::Handle<v8::Value> >::type
+compatibility_throw(v8::Isolate* isolate, v8::Local<v8::Value> exception)
+{
+  return compatibility_throw_impl(isolate, exception, std::integral_constant<bool, v8_uses_isolate>());
+}
+
+inline void
+compatibility_throw_impl(v8::Local<v8::Value> exception, std::true_type)
+{
+  static_cast<_v8_isolate_throw_exception*>(v8::Isolate::GetCurrent())->ThrowException_impl(exception);
+}
+
+inline v8::Handle<v8::Value>
+compatibility_throw_impl(v8::Local<v8::Value> exception, std::false_type)
+{
+  return static_cast<_v8_isolate_throw_exception*>(v8::Isolate::GetCurrent())->ThrowException_impl(exception);
+}
+
+inline std::conditional<v8_uses_isolate, void, v8::Handle<v8::Value> >::type
+compatibility_throw(v8::Local<v8::Value> exception)
+{
+  return compatibility_throw_impl(exception, std::integral_constant<bool, v8_uses_isolate>());
+}
+
+template <typename T, typename U>
+v8::Local<T> compatibility_cast(v8::Local<U> v);
+template <typename T, typename U>
+v8::Local<T> compatibility_cast(U* v);
+
+template <typename Tag>
+struct hack_private_member {
+  /* export it ... */
+  typedef typename Tag::type type;
+  static type ptr;
+};
+
+template <typename Tag>
+typename hack_private_member<Tag>::type hack_private_member<Tag>::ptr;
+
+template <typename Tag, typename Tag::type p>
+struct rob_private_member : hack_private_member<Tag> {
+  /* fill it ... */
+  struct filler {
+    filler() { hack_private_member<Tag>::ptr = p; }
+  };
+  static filler filler_obj;
+};
+
+template<typename Tag, typename Tag::type p>
+typename rob_private_member<Tag, p>::filler rob_private_member<Tag, p>::filler_obj;
+
+template <typename T>
+struct persistent_base_new { typedef T*(*type)(v8::Isolate*, T*); };
+
+template class rob_private_member<persistent_base_new<v8::Value>, &v8::PersistentBase<v8::Value>::New>;
+      
+template <typename T>
+v8::Local<T> make_persistent(v8::Isolate* isolate, v8::Handle<T> v)
+{
+  v8::Value* p = hack_private_member<persistent_base_new<v8::Value>>::ptr
+    (isolate, *compatibility_cast<v8::Value>(v));
+  return compatibility_cast<T>(compatibility_cast<v8::Value>(p));
+}
+
+template <typename T, typename F>
+v8::Local<T> make_weak(v8::Isolate* isolate, v8::Handle<T> v, F&& f)
+{
+  v8::Value* p = hack_private_member<persistent_base_new<v8::Value>>::ptr
+    (isolate, *compatibility_cast<v8::Value>(v));
+  v8::PersistentBase<v8::Value>* persistent = static_cast<v8::PersistentBase<v8::Value>*>
+    (static_cast<void*>(&p));
+
+  auto callback = [](const v8::WeakCallbackInfo<typename std::remove_reference<F>::type>& data) -> void
+    {
+      typename std::remove_reference<F>::type* f = data.GetParameter();
+      (*f)();
+      delete f;
+    };
+
+  persistent->SetWeak(new typename std::remove_reference<F>::type(std::forward<F>(f)),
+                      callback, v8::WeakCallbackType::kParameter);
+  return compatibility_cast<T>(compatibility_cast<v8::Value>(p));
+}
+
+template <typename T>
+struct global_ref
+{
+  global_ref() {}
+  global_ref(v8::Local<T> v)
+    : _value(make_persistent(nullptr, v))
+  {
+  }
+  global_ref(v8::Isolate* isolate, v8::Local<T> v)
+    : _value(make_persistent(isolate, v))
+  {
+  }
+
+  void dispose() const
+  {
+    v8::PersistentBase<T>* p = static_cast<v8::PersistentBase<T>*>(static_cast<void*>(&_value));
+    p->Reset();
+  }
+
+  v8::Handle<T> handle() const { return _value; }
+private:
+  mutable v8::Local<T> _value;
+};
+
+template <typename T = std::integral_constant<bool, v8_uses_isolate> >
+struct _v8_object_internal_field;
+
+template <>
+struct _v8_object_internal_field<std::true_type> : v8::Object
+{
+};
+
+inline void* GetPointerFromInternalField(int) { return nullptr; }
+inline void SetPointerInInternalField(int, void*) {}
+
+template <>
+struct _v8_object_internal_field<std::false_type> : v8::Object
+{
+  void* GetAlignedPointerFromInternalField(int index)
+  {
+    return GetPointerFromInternalField(index);
+  }
+  void SetAlignedPointerInInternalField(int index, void* p)
+  {
+    SetPointerInInternalField(index, p);
+  }
+};
+
+template <typename T = void*>
+inline T compatibility_get_pointer_internal_field(v8::Handle<v8::Object> object, std::size_t index)
+{
+  return reinterpret_cast<T>
+    (static_cast<_v8_object_internal_field<>*>(*object)->GetAlignedPointerFromInternalField(index));
+}
+
+template <typename T>
+inline void compatibility_set_pointer_internal_field(v8::Handle<v8::Object> object, std::size_t index
+                                                     , T* pointer)
+{
+  static_cast<_v8_object_internal_field<>*>(*object)->SetAlignedPointerInInternalField(index, pointer);
+}
+
+template <typename T = void, bool = v8_uses_isolate>
+struct compatibility_handle_scope_impl;
+
+template <typename T>
+struct compatibility_handle_scope_impl<T, true> : v8::HandleScope
+{
+  compatibility_handle_scope_impl()
+    : HandleScope(v8::Isolate::GetCurrent())
+  {}
+  compatibility_handle_scope_impl(v8::Isolate* isolate)
+    : HandleScope((assert(isolate != nullptr), isolate))
+  {}
+};
+
+template <typename T>
+struct compatibility_handle_scope_impl<T, false> : v8::HandleScope
+{
+  compatibility_handle_scope_impl()
+  {}
+  compatibility_handle_scope_impl(v8::Isolate*)
+  {}
+};
+
+using compatibility_handle_scope = compatibility_handle_scope_impl<>;
+
+template <bool = v8_uses_isolate>
+struct _v8_initialize_icu;
+
+template <>
+struct _v8_initialize_icu<true> : v8::V8
+{
+};
+
+template <>
+struct _v8_initialize_icu<false> : v8::V8
+{
+  static bool InitializeICU(const char* = NULL)
+  {
+    return true;
+  }
+};
+
+inline void compatibility_initialize()
+{
+#ifdef HAVE_V8_CREATE_PARAMS
+  constexpr const char* argv[] = {""};
+  static_cast<_v8_initialize_icu<>*>(nullptr)->InitializeICU();
+  v8::V8::InitializeExternalStartupData(argv[0]);
+  v8::V8::Initialize();
+#else
+  v8::V8::Initialize();
+  static_cast<_v8_initialize_icu<>*>(nullptr)->InitializeICU();
+#endif
+}
+
+template <typename T, typename U>
+v8::Local<T> compatibility_cast(v8::Local<U> v)
+{
+  static_assert(sizeof(v8::Local<T>) == sizeof(v8::Local<U>), "");
+  v8::Local<T> l;
+  std::memcpy(&l, &v, sizeof(v8::Local<T>));
+  return l;
+}
+
+template <typename T, typename U>
+v8::Local<T> compatibility_cast(U* v)
+{
+  static_assert(sizeof(v8::Local<T>) == sizeof(U*), "");
+  v8::Local<T> l;
+  std::memcpy(&l, &v, sizeof(v8::Local<T>));
+  return l;
+}
+
+template <typename T = v8::Isolate, bool = v8_uses_isolate>
+struct _v8_get_current_context;
+
+template <typename T>
+struct _v8_get_current_context<T, false> : v8::Context
+{
+};
+
+template <typename T>
+struct _v8_get_current_context<T, true> : T
+{
+  static v8::Local<v8::Context> GetCurrent()
+  {
+    return T::GetCurrent()->GetCurrentContext();
+  }
+};
+
+template <typename T>
+inline v8::Local<v8::Value>
+new_v8_external_instance(v8::Handle<v8::Function>& ctor, T v, v8::Isolate* isolate)
+{
+  // TODO: ensure v8::External ownership ??? (memory leak in case NewInstance throws)
+  v8::Handle<v8::Value> a[] = {efl::eina::js::compatibility_new<v8::External>(isolate, v)};
+  return ctor->NewInstance(1, a);
+}
+
+inline
+compatibility_return_type cast_function(compatibility_callback_info_type args);
+
+inline v8::Local<v8::Value>
+new_v8_external_instance(v8::Handle<v8::Function>& ctor, Eo* v, v8::Isolate* isolate)
+{
+  // TODO: ensure v8::External ownership ??? (memory leak in case NewInstance throws)
+  v8::Handle<v8::Value> a[] = {efl::eina::js::compatibility_new<v8::External>(isolate, v)};
+  auto obj = ctor->NewInstance(1, a);
+  obj->Set(compatibility_new<v8::String>(isolate, "cast"),
+           compatibility_new<v8::FunctionTemplate>(isolate, &cast_function)->GetFunction());
+  return obj;
+}
+
+inline v8::Local<v8::Object> compatibility_global()
+{
+  return _v8_get_current_context<>::GetCurrent()->Global();
+}
+
+EAPI extern std::map<std::string, v8::Local<v8::Function>> constructors_map_;
+
+inline v8::Handle<v8::Function> get_class_constructor(std::string const& class_name)
+{
+  auto it = constructors_map_.find(class_name);
+  if (it == constructors_map_.end())
+    throw std::runtime_error("Class not found");
+  return it->second;
+}
+
+inline void register_class_constructor(std::string const& class_name,
+                                       v8::Handle<v8::Function> constructor_ptr)
+{
+  // TODO: check if already exist?
+  constructors_map_[class_name] = constructor_ptr;
+}
+
+template<class T = v8::StackTrace>
+typename std::enable_if<!v8_uses_isolate, v8::Local<T>>::type
+compatibility_current_stack_trace(v8::Isolate*, int frame_limit,
+                                 v8::StackTrace::StackTraceOptions options)
+{
+  return T::CurrentStackTrace(frame_limit, options);
+}
+
+template<class T = v8::StackTrace>
+typename std::enable_if<v8_uses_isolate, v8::Local<T>>::type
+compatibility_current_stack_trace(v8::Isolate *isolate, int frame_limit,
+                                 v8::StackTrace::StackTraceOptions options)
+{
+  return T::CurrentStackTrace(isolate, frame_limit, options);
+}
+
+inline
+compatibility_return_type cast_function(compatibility_callback_info_type args)
+{
+  auto isolate = args.GetIsolate();
+  compatibility_handle_scope scope(isolate);
+  v8::Local<v8::Value> type;
+  if(args.Length() == 1 && (type = args[0])->IsString())
+    {
+      v8::Local<v8::Object> self = args.This();
+      v8::Local<v8::Value> external = self->GetInternalField(0);
+      Eo* eo = static_cast<Eo*>(v8::External::Cast(*external)->Value());
+
+      v8::String::Utf8Value str(type->ToString());
+      char* class_name = *str;
+
+      auto ctor = ::efl::eina::js::get_class_constructor(class_name);
+      return compatibility_return
+        (new_v8_external_instance(ctor, ::eo_ref(eo), isolate), args);
+    }
+  else
+    {
+      eina::js::compatibility_throw
+        (isolate, v8::Exception::TypeError
+         (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected String type")));
+      return compatibility_return();
+    }
+}
+
+} } }
+
+#endif
diff --git a/src/bindings/js/eina_js/eina_js_container.cc b/src/bindings/js/eina_js/eina_js_container.cc
new file mode 100644 (file)
index 0000000..60c53e0
--- /dev/null
@@ -0,0 +1,495 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eina.hh>
+#include <Eina.h>
+#include <cstdlib>
+
+#include <Eo.h>
+
+#include <eina_integer_sequence.hh>
+#include <eina_tuple.hh>
+#include <eina_ptrlist.hh>
+
+#include <Eina_Js.hh>
+
+#include <tuple>
+
+#include <iostream>
+
+namespace efl { namespace eina { namespace js {
+
+template <typename T>
+struct tag { typedef T type; };
+
+namespace {
+
+global_ref<v8::ObjectTemplate> instance_persistents[container_type_size];
+global_ref<v8::Function> instance_templates[container_type_size];
+
+v8::Local<v8::Value> push(eina_container_base& self, v8::Isolate* isolate, v8::Local<v8::Value> value)
+{
+  return v8::Integer::New(isolate, self.push(isolate, value));
+}
+
+v8::Local<v8::Value> pop(eina_container_base& self, v8::Isolate* isolate, v8::Local<v8::Value>)
+{
+  return self.pop(isolate);
+}
+
+v8::Local<v8::Value> concat(eina_container_base& lhs, v8::Isolate* isolate, v8::Local<v8::Value> other)
+{
+  const char* error_message = 0;
+  if(other->IsObject())
+    {
+      v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(other);
+      v8::String::Utf8Value constructor_name (obj->GetConstructorName());
+      if(obj->GetConstructorName()->Equals(efl::eina::js::compatibility_new<v8::String>(isolate, "eina_list"))
+         || obj->GetConstructorName()->Equals(efl::eina::js::compatibility_new<v8::String>(isolate, "eina_array")))
+        {
+          eina_container_base& rhs = *static_cast<eina_container_base*>
+            (efl::eina::js::compatibility_get_pointer_internal_field(obj, 0));
+          std::type_info const& typeinfo_lhs = typeid(lhs)
+            , &typeinfo_rhs = typeid(rhs);
+          if(!typeinfo_lhs.before(typeinfo_rhs) && !typeinfo_rhs.before(typeinfo_lhs))
+            {
+              v8::Handle<v8::Value> a[] =
+                {efl::eina::js::compatibility_new<v8::External>(isolate, rhs.concat(lhs))};
+              assert(!!*instance_templates[lhs.get_container_type()].handle());
+              v8::Local<v8::Object> result =
+                instance_templates[lhs.get_container_type()].handle()->NewInstance(1, a);
+              return result;
+            }
+          else
+            error_message = "Containers are not of the same type.";
+        }
+      else
+        error_message = "Object to be concatenated is not a container.";
+    }
+  else
+    error_message = "Concatenation argument is not an container";
+
+  eina::js::compatibility_throw
+    (isolate, v8::Exception::TypeError(eina::js::compatibility_new<v8::String>(isolate, error_message)));
+
+  return v8::Undefined(isolate);
+}
+
+v8::Local<v8::Value> slice(eina_container_base& self, v8::Isolate* isolate, v8::Local<v8::Value> begin
+                            , v8::Local<v8::Value> end)
+{
+  std::size_t i, j;
+
+  if(begin->IsUint32() || begin->IsInt32())
+    i = begin->IntegerValue();
+  else if (begin->IsUndefined())
+    i = 0;
+  else
+    return v8::Undefined(isolate);
+
+  if(end->IsUint32() || end->IsInt32())
+    j = end->IntegerValue();
+  else if (end->IsUndefined())
+    j = self.size();
+  else
+    return v8::Undefined(isolate);
+
+  v8::Handle<v8::Value> a[] = {efl::eina::js::compatibility_new<v8::External>(isolate, self.slice(i, j))};
+  v8::Local<v8::Object> result = instance_templates[self.get_container_type()].handle()
+    ->NewInstance(1, a);
+  return result;
+}
+
+compatibility_accessor_getter_return_type length
+  (v8::Local<v8::String>, compatibility_accessor_getter_callback_info_type info)
+{
+  v8::Local<v8::Object> self_obj = compatibility_cast<v8::Object>(info.This());
+  eina_container_base* self = static_cast<eina_container_base*>
+    (compatibility_get_pointer_internal_field(self_obj, 0));
+  return compatibility_return(js::get_value_from_c(self->size(), info.GetIsolate(), ""), info);
+}
+
+compatibility_indexed_property_getset_return_type index_get
+  (uint32_t index, compatibility_indexed_property_callback_info_type info)
+{
+  v8::Local<v8::Object> self_obj = v8::Local<v8::Object>::Cast(info.This());
+  eina_container_base* self = static_cast<eina_container_base*>
+    (compatibility_get_pointer_internal_field(self_obj, 0));
+  return compatibility_return(self->get(info.GetIsolate(), index), info);
+}
+
+compatibility_indexed_property_getset_return_type index_set
+  (uint32_t index, v8::Local<v8::Value> value, compatibility_indexed_property_callback_info_type info)
+{
+  v8::Local<v8::Object> self_obj = v8::Local<v8::Object>::Cast(info.This());
+  eina_container_base* self = static_cast<eina_container_base*>
+    (compatibility_get_pointer_internal_field(self_obj, 0));
+
+  return compatibility_return(self->set(info.GetIsolate(), index, value), info);
+}
+
+
+#define GENERATE_CONTAINER_CONSTRUCT_TYPE_IF(x) GENERATE_CONTAINER_CONSTRUCT_TYPE2_IF(x, x)
+#define GENERATE_CONTAINER_CONSTRUCT_TYPE2_IF(x, y) if (!strcmp(class_name, #x)) \
+    return new Container<y, nonclass_cls_name_getter, typename container_wrapper<y>::type>();
+
+template< template<typename, typename, typename> class Container>
+eina_container_base* construct_container(const char* class_name)
+{
+  GENERATE_CONTAINER_CONSTRUCT_TYPE_IF(int);
+  GENERATE_CONTAINER_CONSTRUCT_TYPE_IF(float);
+  GENERATE_CONTAINER_CONSTRUCT_TYPE2_IF(bool, Eina_Bool);
+  GENERATE_CONTAINER_CONSTRUCT_TYPE2_IF(string, char*);
+
+  return 0;
+}
+
+compatibility_return_type new_eina_list_internal(compatibility_callback_info_type args)
+{
+  if(args.IsConstructCall())
+    {
+      if(args.Length() == 0)
+        {
+          eina_container_base* p = new eina_list<int>;
+          compatibility_set_pointer_internal_field
+            (args.This(), 0, dynamic_cast<void*>(p));
+        }
+      else
+        {
+          if(args[0]->IsExternal())
+            {
+              eina_container_base* base = reinterpret_cast<eina_container_base*>
+                (v8::External::Cast(*args[0])->Value());
+              compatibility_set_pointer_internal_field
+                (args.This(), 0, dynamic_cast<void*>(base));
+            }
+          else
+            std::abort();
+        }
+    }
+  else
+    std::abort();
+  return compatibility_return();
+}
+
+compatibility_return_type new_eina_list(compatibility_callback_info_type args)
+{
+  if(args.IsConstructCall())
+    {
+      if(args.Length() == 0) // Default constructor, list of ints. Or should be list of Eo's?
+        {
+          eina_container_base* p = new eina_list<int>;
+          compatibility_set_pointer_internal_field
+            (args.This(), 0, dynamic_cast<void*>(p));
+          return compatibility_return();
+        }
+        else if (args.Length() == 1 && args[0]->IsString())
+        {
+          v8::String::Utf8Value string(args[0]);
+          eina_container_base* p = construct_container<efl::eina::js::eina_list>(*string);
+          if (!p) {
+             return eina::js::compatibility_throw
+              (args.GetIsolate(), v8::Exception::TypeError
+                (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Invalid type for container.")));
+          }
+          compatibility_set_pointer_internal_field
+            (args.This(), 0, dynamic_cast<void*>(p));
+          return compatibility_return();
+        }
+    }
+  return eina::js::compatibility_throw
+    (args.GetIsolate(), v8::Exception::TypeError
+     (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Wrong number of arguments for constructor call")));
+}
+
+compatibility_return_type new_eina_array_internal(compatibility_callback_info_type args)
+{
+  if(args.IsConstructCall())
+    {
+      if(args.Length() == 0)
+        {
+          eina_container_base* p = new eina_array<int>;
+          compatibility_set_pointer_internal_field
+            (args.This(), 0, dynamic_cast<void*>(p));
+        }
+      else
+        {
+          if(args[0]->IsExternal())
+            {
+              eina_container_base* base = reinterpret_cast<eina_container_base*>
+                (v8::External::Cast(*args[0])->Value());
+              compatibility_set_pointer_internal_field
+                (args.This(), 0, dynamic_cast<void*>(base));
+            }
+          else
+            std::abort();
+        }
+    }
+  else
+    std::abort();
+  return compatibility_return();
+}
+
+compatibility_return_type new_eina_array(compatibility_callback_info_type args)
+{
+  if(args.IsConstructCall())
+    {
+      if(args.Length() == 0)
+        {
+          eina_container_base* p = new eina_array<int>;
+          compatibility_set_pointer_internal_field
+            (args.This(), 0, dynamic_cast<void*>(p));
+          return compatibility_return();
+        }
+        else if (args.Length() == 1 && args[0]->IsString())
+        {
+          v8::String::Utf8Value string(args[0]);
+          eina_container_base* p = construct_container<efl::eina::js::eina_array>(*string);
+          if (!p) {
+             return eina::js::compatibility_throw
+              (args.GetIsolate(), v8::Exception::TypeError
+                (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Invalid type for container.")));
+          }
+          compatibility_set_pointer_internal_field
+            (args.This(), 0, dynamic_cast<void*>(p));
+          return compatibility_return();
+        }
+    }
+  return eina::js::compatibility_throw
+    (args.GetIsolate(), v8::Exception::TypeError
+     (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Wrong number of arguments for constructor call")));
+}
+
+template <typename F>
+struct function_params;
+
+template <typename R, typename... Sig>
+struct function_params<R(*)(Sig...)>
+{
+  typedef std::tuple<Sig...> type;
+};
+
+template <typename F>
+struct function_result;
+
+template <typename R, typename... Sig>
+struct function_result<R(*)(Sig...)>
+{
+  typedef R type;
+};
+
+template <typename T>
+struct is_persistent : std::false_type {};
+
+template <typename...A>
+struct is_persistent<v8::Persistent<A...> > : std::true_type {};
+
+template <std::size_t I, typename Sig>
+typename std::tuple_element<I, Sig>::type
+get_element(v8::Isolate* isolate
+            , compatibility_callback_info_type args
+            , typename std::enable_if
+            <is_persistent<typename std::tuple_element<I, Sig>::type>::value>::type* = 0)
+{
+  return typename std::tuple_element<I, Sig>::type(isolate, args[I]);
+}
+
+template <std::size_t I, typename Sig>
+typename std::tuple_element<I, Sig>::type
+get_element(v8::Isolate* /*isolate*/
+            , compatibility_callback_info_type args
+            , typename std::enable_if
+            <!is_persistent<typename std::tuple_element<I, Sig>::type>::value>::type* = 0)
+{
+  return args[I];
+}
+
+template <typename Sig, typename R, typename T, typename F, std::size_t... N>
+R call_impl(v8::Isolate* isolate
+            , compatibility_callback_info_type args
+            , T* self, F* f
+            , eina::index_sequence<N...>)
+{
+  assert(self != 0);
+  return (*f)(*self, isolate, js::get_element<N, Sig>(isolate, args)...);
+}
+
+template <typename Sig, typename T, typename F, typename R>
+compatibility_return_type call_generic_impl(compatibility_callback_info_type args, tag<R>)
+{
+  T* self = static_cast<T*>
+    (compatibility_get_pointer_internal_field<>(args.This(), 0));
+  F* f = reinterpret_cast<F*>(v8::External::Cast(*args.Data())->Value());
+  return compatibility_return
+    (js::get_value_from_c
+     (js::call_impl<Sig, R>(args.GetIsolate(), args, self, f
+                            , eina::make_index_sequence<std::tuple_size<Sig>::value>())
+      , args.GetIsolate(), "")
+     , args);
+}
+
+template <typename Sig, typename T, typename F>
+compatibility_return_type call_generic_impl(compatibility_callback_info_type args, tag<void>)
+{
+  T* self = static_cast<T*>
+    (compatibility_get_pointer_internal_field(args.This(), 0));
+  F* f = reinterpret_cast<F*>(v8::External::Cast(*args.Data())->Value());
+  js::call_impl<Sig, void>(args.GetIsolate(), args, self, f
+                           , eina::make_index_sequence<std::tuple_size<Sig>::value>());
+  return compatibility_return();
+}
+
+template <typename Sig, typename R, typename T, typename F>
+compatibility_return_type call_generic(compatibility_callback_info_type args)
+{
+  return efl::eina::js::call_generic_impl<Sig, T, F>(args, tag<R>());
+}
+
+template <typename Sig, typename T, typename F, typename R>
+compatibility_return_type call_function_impl(compatibility_callback_info_type args, tag<R>)
+{
+  T* self = static_cast<T*>
+    (compatibility_get_pointer_internal_field(args.This(), 0));
+  F f = reinterpret_cast<F>(v8::External::Cast(*args.Data())->Value());
+  return compatibility_return
+    (/*js::get_value_from_c*/
+     (js::call_impl<Sig, R>(args.GetIsolate(), args, self, f
+                            , eina::make_index_sequence<std::tuple_size<Sig>::value>())
+      /*, args.GetIsolate(), ""*/)
+     , args);
+}
+
+template <typename Sig, typename T, typename F>
+compatibility_return_type call_function_impl(compatibility_callback_info_type args, tag<void>)
+{
+  T* self = static_cast<T*>
+    (compatibility_get_pointer_internal_field(args.This(), 0));
+  F f = reinterpret_cast<F>(v8::External::Cast(*args.Data())->Value());
+  js::call_impl<Sig, void>(args.GetIsolate(), args, self, f
+                           , eina::make_index_sequence<std::tuple_size<Sig>::value>());
+  return compatibility_return();
+}
+
+template <typename Sig, typename R, typename T, typename F>
+compatibility_return_type call_function(compatibility_callback_info_type args)
+{
+  return efl::eina::js::call_function_impl<Sig, T, F>(args, tag<R>());
+}
+
+template <typename T, typename F>
+void register_(v8::Isolate* isolate, const char* name, F f, v8::Handle<v8::ObjectTemplate> template_
+               , typename std::enable_if<std::is_function<typename std::remove_pointer<F>::type>::value>::type* = 0)
+{
+  template_->Set(compatibility_new<v8::String>(isolate, name)
+                 , compatibility_new<v8::FunctionTemplate>
+                 (isolate, &efl::eina::js::call_function
+                  <typename eina::_mpl::pop_front<typename function_params<F>::type, 2u>::type
+                  , typename function_result<F>::type, T, F>
+                  , compatibility_new<v8::External>
+                  (isolate, reinterpret_cast<void*>(f))));
+}
+
+template <typename T, typename...Sig, typename F>
+void register_(v8::Isolate* isolate, const char* name, F&& f, v8::Handle<v8::ObjectTemplate> template_
+               , typename std::enable_if<!std::is_function<typename std::remove_pointer<F>::type>::value>::type* = 0)
+{
+  using result_type = decltype
+                        (std::declval<F>()
+                         (std::declval<T&>(), std::declval<v8::Isolate*>()
+                          , std::declval<Sig>()...)
+                        );
+  template_->Set(compatibility_new<v8::String>(isolate, name)
+                 , compatibility_new<v8::FunctionTemplate>
+                 (isolate
+                  , &efl::eina::js::call_generic<std::tuple<Sig...>, result_type, T, F>
+                  , compatibility_new<v8::External>
+                  (isolate, new F(std::forward<F>(f)))));
+}
+
+v8::Local<v8::ObjectTemplate> register_template(v8::Isolate* isolate, v8::Handle<v8::FunctionTemplate> constructor)
+{
+  v8::Local<v8::ObjectTemplate> instance_t = constructor->InstanceTemplate();
+  instance_t->SetInternalFieldCount(1);
+
+  instance_t->SetIndexedPropertyHandler(& efl::eina::js::index_get, & efl::eina::js::index_set);
+
+  v8::Local<v8::ObjectTemplate> prototype = constructor->PrototypeTemplate();
+  prototype->SetAccessor(compatibility_new<v8::String>(isolate, "length"), &efl::eina::js::length);
+
+  using namespace std::placeholders;
+  js::register_<js::eina_container_base>
+    (isolate, "push", &js::push, prototype);
+  js::register_<js::eina_container_base>
+    (isolate, "pop", &js::pop, prototype);
+  js::register_<js::eina_container_base>
+    (isolate, "concat", &js::concat, prototype);
+  js::register_<js::eina_container_base>
+    (isolate, "slice", &js::slice, prototype);
+  js::register_<js::eina_container_base>
+    (isolate, "toString", std::bind(&js::eina_container_base::to_string, _1, _2), prototype);
+  js::register_<js::eina_container_base, v8::Local<v8::Value> >
+    (isolate, "join", std::bind(&js::eina_container_base::join, _1, _2, _3), prototype);
+  js::register_<js::eina_container_base, v8::Local<v8::Value> >
+    (isolate, "indexOf", std::bind(&js::eina_container_base::index_of, _1, _2, _3), prototype);
+  js::register_<js::eina_container_base, v8::Local<v8::Value> >
+    (isolate, "lastIndexOf", std::bind(&js::eina_container_base::last_index_of, _1, _2, _3), prototype);
+
+  return instance_t;
+}
+
+void register_class(v8::Isolate* isolate, container_type type, const char* class_name
+                    , compatibility_function_callback callback)
+{
+  v8::Handle<v8::FunctionTemplate> constructor
+    = compatibility_new<v8::FunctionTemplate>(isolate, callback);
+  constructor->SetClassName(compatibility_new<v8::String>(isolate, class_name));
+
+  v8::Local<v8::ObjectTemplate> instance_t = efl::eina::js::register_template(isolate, constructor);
+
+  efl::eina::js::instance_persistents[type] = global_ref<v8::ObjectTemplate>{isolate, instance_t};
+  efl::eina::js::instance_templates[type] = global_ref<v8::Function>{isolate, constructor->GetFunction()};
+}
+void register_class(v8::Isolate* isolate, container_type, const char* class_name_
+                    , const char* constructor_name_
+                    , compatibility_function_callback callback
+                    , v8::Handle<v8::Object> exports)
+{
+  v8::Handle<v8::FunctionTemplate> constructor
+    = compatibility_new<v8::FunctionTemplate>(isolate, callback);
+  auto class_name = compatibility_new<v8::String>(isolate, class_name_);
+  auto constructor_name = compatibility_new<v8::String>(isolate, constructor_name_);
+  constructor->SetClassName(class_name);
+
+  v8::Local<v8::ObjectTemplate> instance_t = efl::eina::js::register_template(isolate, constructor);
+  (void)instance_t;
+
+  exports->Set(constructor_name, constructor->GetFunction());
+}
+
+}
+
+EAPI v8::Handle<v8::Function> get_list_instance_template()
+{
+  return efl::eina::js::instance_templates[efl::eina::js::list_container_type].handle();
+}
+
+EAPI v8::Handle<v8::Function> get_array_instance_template()
+{
+  return efl::eina::js::instance_templates[efl::eina::js::array_container_type].handle();
+}
+
+} } }
+
+EAPI void eina_container_register(v8::Handle<v8::Object> exports, v8::Isolate* isolate)
+{
+  efl::eina::js::register_class(isolate, efl::eina::js::list_container_type
+                                , "eina_list", &efl::eina::js::new_eina_list_internal);
+  efl::eina::js::register_class(isolate, efl::eina::js::list_container_type
+                                , "eina_list", "List", &efl::eina::js::new_eina_list, exports);
+  efl::eina::js::register_class(isolate, efl::eina::js::array_container_type
+                                , "eina_array", &efl::eina::js::new_eina_array_internal);
+  efl::eina::js::register_class(isolate, efl::eina::js::array_container_type
+                                , "eina_array", "Array", &efl::eina::js::new_eina_array, exports);
+}
+
diff --git a/src/bindings/js/eina_js/eina_js_container.hh b/src/bindings/js/eina_js/eina_js_container.hh
new file mode 100644 (file)
index 0000000..21343fd
--- /dev/null
@@ -0,0 +1,351 @@
+#ifndef EINA_JS_CONTAINER_HH
+#define EINA_JS_CONTAINER_HH
+
+#include <algorithm>
+
+#include <eina_js_compatibility.hh>
+#include <eina_js_get_value.hh>
+#include <eina_js_get_value_from_c.hh>
+
+struct _Elm_Calendar_Mark;
+struct Elm_Gen_Item;
+struct _Eina_Rectangle;
+struct _Evas_Textblock_Rectangle;
+struct _Elm_Map_Overlay;
+
+namespace efl { namespace eina { namespace js {
+
+namespace detail {
+
+template <typename T>
+eina_container_base* concat(T const& self, eina_container_base const& other)
+{
+  T const& rhs = static_cast<T const&>(other);
+  typedef typename T::container_type container_type;
+  container_type container(self._container.begin(), self._container.end());
+  container.insert(container.end(), rhs._container.begin(), rhs._container.end());
+  return new T(container.release_native_handle());
+}
+
+template <typename T>
+eina_container_base* slice(T const& self, std::int64_t i, std::int64_t j)
+{
+  typedef typename T::container_type container_type;
+  container_type container(std::next(self._container.begin(), i), std::next(self._container.begin(), j));
+  return new T(container.release_native_handle());
+}
+
+// T, W from the container instantiation
+template<typename T, typename W, typename C>
+int push(v8::Isolate* isolate, C& self, v8::Local<v8::Value> v)
+{
+  try
+      {
+         W value = container_wrap(get_value_from_javascript(v, isolate, "", value_tag<T>()));
+         self._container.push_back(value);
+      }
+    catch (std::logic_error const&)
+      {
+         return -1;
+      }
+    return self.size();
+}
+
+template<typename T, typename W, typename K, typename C>
+v8::Local<v8::Value> pop(v8::Isolate* isolate, C& self)
+{
+
+  if (self._container.empty())
+    return v8::Undefined(isolate);
+
+  auto value = eina::js::get_value_from_c(
+       eina::js::wrap_value<T>(eina::js::container_unwrap(self._container.back()), eina::js::value_tag<T>{})
+       , isolate
+       , K::class_name());
+  self._container.pop_back();
+  return value;
+}
+template<typename T, typename W, typename C>
+v8::Local<v8::Value> set(v8::Isolate* isolate, C& self, std::size_t index, v8::Local<v8::Value> v)
+  {
+    using notag_type = typename remove_tag<T>::type;
+    try
+      {
+         W value = container_wrap(get_value_from_javascript(v, isolate, "", value_tag<T>()));
+
+         if (index >= self.size())
+           {
+               std::size_t items_to_add = index - self.size() + 1;
+               for (int i = items_to_add; i; i--)
+                 {
+                    self._container.push_back(container_wrap(notag_type{}));
+                 }
+           }
+
+         auto v2 = std::next(self._container.begin(), index);
+         *v2 = value;
+      }
+    catch (std::logic_error const&)
+      {
+         return v8::Undefined(isolate);
+      }
+
+    return v;
+  }
+
+}
+
+template <typename InputIterator, typename T>
+inline InputIterator find_element(InputIterator first, InputIterator last, T const& value, typename std::enable_if<is_handable_by_value<T>::value>::type* = 0)
+{
+  return std::find(first, last, value);
+}
+
+template <typename InputIterator, typename T>
+inline InputIterator find_element(InputIterator first, InputIterator last, T const& value, typename std::enable_if<!is_handable_by_value<T>::value>::type* = 0)
+{
+  return std::find_if(first, last, [&](T const& e){ return &e == &value; });
+}
+
+template <typename InputIterator>
+inline InputIterator find_element(InputIterator first, InputIterator last, char * value)
+{
+  return std::find_if(first, last, [=](char* e){ return strcmp(e, value) == 0; });
+}
+
+template <typename CharT, typename T>
+inline void stream_element(std::basic_ostream<CharT>& s, T const& value, typename std::enable_if<is_handable_by_value<T>::value>::type* = 0)
+{
+  s << value;
+}
+
+template <typename CharT, typename T>
+inline void stream_element(std::basic_ostream<CharT>& s, T const& value, typename std::enable_if<!is_handable_by_value<T>::value>::type* = 0)
+{
+  s << &value;
+}
+
+template <typename CharT>
+inline void stream_element(std::basic_ostream<CharT>& s, Eina_Bool value)
+{
+  s << (value ? "true" : "false");
+}
+
+template <typename C, typename T, typename K>
+struct eina_container_common;
+
+
+template <typename C, typename V, typename T, typename K, typename Enable = void>
+struct eina_container_type_specific
+  : eina_container_base
+{
+  v8::Local<v8::Value> get(v8::Isolate* isolate, std::size_t index) const
+  {
+     if(index >= this->size())
+       return v8::Undefined(isolate);
+     return eina::js::get_value_from_c(
+       eina::js::wrap_value<T>(eina::js::container_unwrap(*std::next(container_get().begin(), index)), eina::js::value_tag<T>{})
+       , isolate
+       , K::class_name());
+  }
+  int index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const
+  {
+    try
+      {
+        V value = container_wrap(get_value_from_javascript(
+           v, isolate, K::class_name(), eina::js::value_tag<T>{}, false));
+        typedef typename C::const_iterator iterator;
+        iterator first = container_get().cbegin()
+          , last = container_get().cend()
+          , found = find_element(first, last, value);
+        if(found == last)
+          return -1;
+        else
+          return std::distance(first, found);
+      }
+    catch (std::logic_error const&)
+      {
+         return -1;
+      }
+  }
+  int last_index_of(v8::Isolate* isolate, v8::Local<v8::Value> v) const
+  {
+    try
+      {
+        V value = container_wrap(get_value_from_javascript(
+          v, isolate, K::class_name(), eina::js::value_tag<T>{}, false));
+        auto last = container_get().crend()
+          , found = find_element(container_get().crbegin(), last, value);
+        if(found == last)
+          return -1;
+        else
+          return std::distance(container_get().cbegin(), found.base()) -1;
+      }
+    catch (std::logic_error const&)
+      {
+         return -1;
+      }
+  }
+  void* get_container_native_handle()
+  {
+    void const* h = container_get().native_handle();
+    return const_cast<void*>(h);
+  }
+  void const* get_container_native_handle() const
+  {
+    return container_get().native_handle();
+  }
+  C& container_get() { return static_cast<eina_container_common<C, T, K>&>(*this)._container; }
+  C const& container_get() const { return static_cast<eina_container_common<C, T, K>const&>(*this)._container; }
+};
+
+template <typename C, typename T, typename K>
+struct eina_container_common : eina_container_type_specific<C, typename C::value_type, T, K>
+{
+  eina_container_common() : _container() {}
+  eina_container_common(typename C::native_handle_type raw) : _container(raw) {}
+
+  std::size_t size() const { return _container.size(); }
+  v8::Local<v8::String> to_string(v8::Isolate* isolate) const
+  {
+    return join(isolate, compatibility_new<v8::String>(isolate, ","));
+  }
+
+  v8::Local<v8::String> join(v8::Isolate* isolate, v8::Local<v8::Value> separator_js) const
+  {
+    std::string separator = ",";
+    typedef typename container_type::const_iterator iterator;
+    std::stringstream s;
+
+    if (separator_js->IsString())
+      {
+        v8::String::Utf8Value str(separator_js);
+        if (*str)
+          {
+            separator = *str;
+          }
+        else
+          {
+            eina::js::compatibility_throw(
+              isolate, v8::Exception::TypeError(
+                eina::js::compatibility_new<v8::String>(isolate, "Invalid separator.")));
+            return compatibility_new<v8::String>(isolate, "");
+          }
+      }
+    else if (!separator_js->IsUndefined()) // Called join without arguments.
+      {
+        eina::js::compatibility_throw(
+          isolate, v8::Exception::TypeError(
+            eina::js::compatibility_new<v8::String>(isolate, "Separator must be a string.")));
+        return compatibility_new<v8::String>(isolate, "");
+      }
+
+    for(iterator first = _container.begin()
+          , last = _container.end()
+          , last_elem = std::next(last, -1); first != last; ++first)
+      {
+        stream_element(s, *first);
+        if(first !=  last_elem)
+          s << separator;
+      }
+    return compatibility_new<v8::String>(isolate, s.str().c_str());
+  }
+
+  // Default implementation of some methods
+  int push(v8::Isolate* isolate, v8::Local<v8::Value>)
+  {
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Push method was not implemented.")));
+    return -1;
+  }
+  v8::Local<v8::Value> pop(v8::Isolate* isolate)
+  {
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Pop method was not implemented.")));
+    return v8::Undefined(isolate);
+  }
+  v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t, v8::Local<v8::Value>)
+  {
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Indexed attribution was not implemented.")));
+    return v8::Undefined(isolate);
+  }
+  C _container;
+  typedef C container_type;
+};
+
+
+// Specialization for problematic types
+struct empty_container_base
+  : eina_container_base
+{
+  empty_container_base() {}
+  virtual ~empty_container_base() {}
+
+  std::size_t size() const
+  {
+    return 0;
+  }
+  eina_container_base* concat(eina_container_base const& ) const
+  {
+    return new empty_container_base;
+  }
+  eina_container_base* slice(std::int64_t , std::int64_t ) const
+  {
+    return new empty_container_base;
+  }
+  int index_of(v8::Isolate*, v8::Local<v8::Value>) const
+  {
+    return -1;
+  }
+  int last_index_of(v8::Isolate*, v8::Local<v8::Value>) const
+  {
+    return -1;
+  }
+  v8::Local<v8::Value> get(v8::Isolate* isolate, std::size_t) const
+  {
+    return v8::Undefined(isolate);
+  }
+  v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t, v8::Local<v8::Value>)
+  {
+    return v8::Undefined(isolate);
+  }
+  int push(v8::Isolate*, v8::Local<v8::Value>)
+  {
+    return -1;
+  }
+  v8::Local<v8::Value> pop(v8::Isolate* isolate)
+  {
+    return v8::Undefined(isolate);
+  }
+  v8::Local<v8::String> to_string(v8::Isolate* isolate) const
+  {
+    return compatibility_new<v8::String>(isolate, "");
+  }
+  v8::Local<v8::String> join(v8::Isolate* isolate, v8::Local<v8::Value>) const
+  {
+    return compatibility_new<v8::String>(isolate, "");
+  }
+  container_type get_container_type() const
+  {
+    throw std::runtime_error("get_container_type of container with unmanagable type");
+    return container_type_size;
+  }
+  void* get_container_native_handle()
+  {
+    return nullptr;
+  }
+  void const* get_container_native_handle() const
+  {
+    return nullptr;
+  }
+};
+
+} } }
+
+EAPI void eina_container_register(v8::Handle<v8::Object> exports, v8::Isolate* isolate);
+
+#endif
diff --git a/src/bindings/js/eina_js/eina_js_error.cc b/src/bindings/js/eina_js/eina_js_error.cc
new file mode 100644 (file)
index 0000000..89d69a1
--- /dev/null
@@ -0,0 +1,24 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eina_Js.hh>
+
+namespace efl { namespace eina {namespace js {
+
+EAPI
+js::compatibility_return_type convert_error_to_javascript_exception(v8::Isolate *isolate)
+{
+     Eina_Error err = eina_error_get();
+     if (!err)
+       return compatibility_return();
+
+  v8::Local<v8::Object> je = eina::js::compatibility_new<v8::Object>(isolate);
+     je->Set(compatibility_new<v8::String>(isolate, "code"),
+             compatibility_new<v8::String>(isolate, "Eina_Error"));
+     je->Set(compatibility_new<v8::String>(isolate, "value"),
+             compatibility_new<v8::String>(isolate, eina_error_msg_get(err)));
+     return compatibility_throw(isolate, je);
+}
+
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/eina_js/eina_js_error.hh b/src/bindings/js/eina_js/eina_js_error.hh
new file mode 100644 (file)
index 0000000..49cef35
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef EINA_JS_ERROR_HH
+#define EINA_JS_ERROR_HH
+
+#include <eina_js_compatibility.hh>
+
+namespace efl { namespace eina { namespace js {
+
+/**
+ * Converts the error value set through Eina's error tool to a JavaScript
+ * exception.
+ *
+ * The exception object will have a `code` string field with the `"Eina_Error"`
+ * string value and a `value` string field with the value extracted from
+ * `eina_error_msg_get`.
+ *
+ * It won't reset the error to NULL, so you can still access the error object,
+ * but if you keep calling this function without clearing the error, a new
+ * exception will be generated for each call after some error is reached. We,
+ * therefore, suggest you to call `eina_error_set(0)` afterwards.
+ */
+js::compatibility_return_type convert_error_to_javascript_exception(v8::Isolate *isolate);
+
+} } } // namespace efl::eina::js
+
+#endif /* EINA_JS_ERROR_HH */
diff --git a/src/bindings/js/eina_js/eina_js_get_value.hh b/src/bindings/js/eina_js/eina_js_get_value.hh
new file mode 100644 (file)
index 0000000..637b48a
--- /dev/null
@@ -0,0 +1,449 @@
+#ifndef EFL_EINA_JS_GET_VALUE_HH
+#define EFL_EINA_JS_GET_VALUE_HH
+
+#include <eina_js_compatibility.hh>
+
+#include <type_traits>
+#include <cstdlib>
+#include <iostream>
+#include <typeinfo>
+
+namespace efl { namespace eina { namespace js {
+
+template <typename T>
+inline int get_value_from_javascript
+  (v8::Local<v8::Value> v
+   , v8::Isolate* isolate
+   , const char*
+   , value_tag<T>
+   , bool throw_js_exception = true
+   , typename std::enable_if<(std::is_integral<T>::value && !std::is_same<T, Eina_Bool>::value)>::type* = 0)
+{
+  if(v->IsInt32())
+    return v->Int32Value();
+  else if(v->IsUint32())
+    return v->Uint32Value();
+  else
+    {
+      if (throw_js_exception)
+        eina::js::compatibility_throw
+          (isolate, v8::Exception::TypeError
+           (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Integral type")));
+
+      throw std::logic_error("");
+    }
+  return 0;
+}
+
+inline char* get_value_from_javascript
+  (v8::Local<v8::Value> v
+   , v8::Isolate* isolate
+   , const char*
+   , value_tag<char*>
+   , bool throw_js_exception = true)
+{
+  if(v->IsNull())
+    return nullptr;
+  else if(v->IsString())
+    {
+      v8::String::Utf8Value str(v->ToString());
+      char* string = strdup(*str); // TODO: leaks
+      return string;
+    }
+  else
+    {
+      if (throw_js_exception)
+        eina::js::compatibility_throw
+          (isolate, v8::Exception::TypeError
+           (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected String type")));
+
+      throw std::logic_error("");
+    }
+  return 0;
+}
+
+inline const char* get_value_from_javascript
+  (v8::Local<v8::Value> v
+   , v8::Isolate* isolate
+   , const char* class_name
+   , value_tag<const char*>
+   , bool throw_js_exception = true)
+{
+  return get_value_from_javascript(v, isolate, class_name, value_tag<char*>(), throw_js_exception);
+}
+
+inline Eo* get_value_from_javascript
+  (v8::Local<v8::Value> v
+   , v8::Isolate* isolate
+   , const char*
+   , value_tag<Eo*>
+   , bool throw_js_exception = true)
+{
+  if(v->IsNull())
+    return nullptr;
+  else if(v->IsObject())
+    {
+      v8::Local<v8::Object> object = v->ToObject();
+      if(object->InternalFieldCount() == 1)
+        {
+          v8::Local<v8::Value> r = object->GetInternalField(0);
+          if(v8::External* external = v8::External::Cast(*r))
+            {
+              return static_cast<Eo*>(external->Value());
+            }
+        }
+    }
+  if (throw_js_exception)
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian object type")));
+  throw std::logic_error("");
+  return nullptr;
+}
+
+inline Eo* get_value_from_javascript
+  (v8::Local<v8::Value> v
+   , v8::Isolate* isolate
+   , const char* class_name
+   , value_tag<Eo* const>
+   , bool throw_js_exception = true)
+{
+  return get_value_from_javascript(v, isolate, class_name, value_tag<Eo*>(), throw_js_exception);
+}
+
+template <typename T>
+inline T get_value_from_javascript
+  (v8::Local<v8::Value> v
+   , v8::Isolate* isolate
+   , const char*
+   , value_tag<struct_ptr_tag<T>>
+   , bool throw_js_exception = true)
+{
+  if(v->IsNull())
+    return nullptr;
+  else if(v->IsObject())
+    {
+      v8::Local<v8::Object> object = v->ToObject();
+      if(object->InternalFieldCount() == 1)
+        {
+           return compatibility_get_pointer_internal_field<T>(object, 0);
+        }
+    }
+  if (throw_js_exception)
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian struct type")));
+  throw std::logic_error("");
+  return nullptr;
+}
+
+template <typename T>
+inline T get_value_from_javascript
+  (v8::Local<v8::Value> v
+   , v8::Isolate* isolate
+   , const char* class_name
+   , value_tag<struct_tag<T>>
+   , bool throw_js_exception = true)
+{
+  T* ptr = get_value_from_javascript(v, isolate, class_name, value_tag<struct_ptr_tag<T*>>(), throw_js_exception);
+  if (ptr)
+    return *ptr;
+
+  if (throw_js_exception)
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Conversion of null pointer to by-value struct.")));
+  throw std::logic_error("");
+  return T{};
+}
+
+template <typename T>
+inline T get_value_from_javascript
+  (v8::Local<v8::Value> v
+   , v8::Isolate* isolate
+   , const char*
+   , value_tag<T>
+   , bool throw_js_exception = true
+   , typename std::enable_if<std::is_enum<T>::value>::type* = 0)
+{
+  if(v->IsInt32())
+    return static_cast<T>(v->Int32Value());
+  else if(v->IsUint32())
+    return static_cast<T>(v->Uint32Value());
+  else
+    {
+      if (throw_js_exception)
+        eina::js::compatibility_throw
+          (isolate, v8::Exception::TypeError
+           (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected enumeration type")));
+
+      throw std::logic_error("");
+    }
+  return T();
+}
+
+inline Eina_Bool get_value_from_javascript
+  (v8::Local<v8::Value> v
+   , v8::Isolate* isolate
+   , const char*
+   , value_tag<Eina_Bool>
+   , bool throw_js_exception = true)
+{
+  if(v->IsBoolean() || v->IsBooleanObject())
+    {
+      return v->BooleanValue() ? EINA_TRUE : EINA_FALSE;
+    }
+  else
+    {
+      if (throw_js_exception)
+        eina::js::compatibility_throw
+          (isolate, v8::Exception::TypeError
+           (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Boolean type")));
+
+      throw std::logic_error("");
+    }
+  return 0;
+}
+
+template <typename T>
+inline double get_value_from_javascript
+  (v8::Local<v8::Value> v
+   , v8::Isolate* isolate
+   , const char*
+   , value_tag<T>
+   , bool throw_js_exception = true
+   , typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
+{
+  if(v->IsNumber())
+    {
+      return v->NumberValue();
+    }
+  else
+    {
+      if (throw_js_exception)
+        eina::js::compatibility_throw
+          (isolate, v8::Exception::TypeError
+           (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected floating point type")));
+      throw std::logic_error("");
+    }
+  return 0.0;
+}
+
+template <typename T>
+inline T get_value_from_javascript
+  (v8::Local<v8::Value>, v8::Isolate* isolate, const char*, value_tag<T>
+   , bool throw_js_exception = true
+   , typename std::enable_if<
+     !std::is_floating_point<T>::value &&
+     !std::is_integral<T>::value &&
+     !std::is_enum<T>::value &&
+     !js::is_struct_tag<T>::value &&
+     !js::is_struct_ptr_tag<T>::value &&
+     !js::is_complex_tag<T>::value &&
+     !std::is_same<T, Eina_Accessor*>::value &&
+     !std::is_same<T, Eina_Array*>::value &&
+     !std::is_same<T, Eina_Iterator*>::value &&
+     !std::is_same<T, Eina_Hash*>::value &&
+     !std::is_same<T, Eina_List*>::value &&
+     !std::is_same<T, const Eina_Accessor*>::value &&
+     !std::is_same<T, const Eina_Array*>::value &&
+     !std::is_same<T, const Eina_Iterator*>::value &&
+     !std::is_same<T, const Eina_Hash*>::value &&
+     !std::is_same<T, const Eina_List*>::value
+   >::type* = 0)
+{
+  if (throw_js_exception)
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Not implemented yet")));
+  throw std::logic_error("");
+}
+
+// TODO: Fix for const types
+template <typename T, typename K>
+inline Eina_Accessor* get_value_from_javascript(
+  v8::Local<v8::Value> v,
+  v8::Isolate* isolate,
+  const char*,
+  value_tag<complex_tag<Eina_Accessor *, T, K>>,
+  bool throw_js_exception = true)
+{
+  if(v->IsNull())
+    return nullptr;
+  else if(v->IsObject())
+    {
+      using wrapped_type = typename container_wrapper<T>::type;
+      v8::Local<v8::Object> object = v->ToObject();
+      auto& acc = import_accessor<wrapped_type>(object);
+      return acc.native_handle();
+    }
+  if (throw_js_exception)
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian accessor type")));
+  throw std::logic_error("");
+}
+
+template <typename...I>
+inline const Eina_Accessor* get_value_from_javascript(
+  v8::Local<v8::Value> v,
+  v8::Isolate* isolate,
+  const char* class_name,
+  value_tag<complex_tag<const Eina_Accessor *, I...>>,
+  bool throw_js_exception = true)
+{
+  return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_Accessor *, I...>>{}, throw_js_exception);
+}
+
+template <typename...I>
+inline Eina_Array* get_value_from_javascript(
+  v8::Local<v8::Value> v,
+  v8::Isolate* isolate,
+  const char*,
+  value_tag<complex_tag<Eina_Array *, I...>>,
+  bool throw_js_exception = true)
+{
+  if(v->IsNull())
+    return nullptr;
+  else if(v->IsObject())
+    {
+      v8::Local<v8::Object> object = v->ToObject();
+      if(object->InternalFieldCount() == 1)
+        {
+           eina_container_base* cbase = compatibility_get_pointer_internal_field<eina_container_base*>(object, 0);
+           return static_cast<Eina_Array*>(cbase->get_container_native_handle());
+        }
+    }
+  if (throw_js_exception)
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian list type")));
+  throw std::logic_error("");
+  return nullptr;
+}
+
+template <typename...I>
+inline const Eina_Array* get_value_from_javascript(
+  v8::Local<v8::Value> v,
+  v8::Isolate* isolate,
+  const char* class_name,
+  value_tag<complex_tag<const Eina_Array *, I...>>,
+  bool throw_js_exception = true)
+{
+  return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_Array *, I...>>{}, throw_js_exception);
+}
+
+template <typename...I>
+inline Eina_Iterator* get_value_from_javascript(
+  v8::Local<v8::Value>,
+  v8::Isolate* isolate,
+  const char*,
+  value_tag<complex_tag<Eina_Iterator *, I...>> tag,
+  bool throw_js_exception = true)
+{
+  if (throw_js_exception)
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Not implemented yet")));
+  throw std::logic_error("");
+}
+
+template <typename...I>
+inline const Eina_Iterator* get_value_from_javascript(
+  v8::Local<v8::Value> v,
+  v8::Isolate* isolate,
+  const char* class_name,
+  value_tag<complex_tag<const Eina_Iterator *, I...>>,
+  bool throw_js_exception = true)
+{
+  return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_Iterator *, I...>>{}, throw_js_exception);
+}
+
+template <typename T, typename...U>
+inline Eina_Hash* get_value_from_javascript(
+  v8::Local<v8::Value>,
+  v8::Isolate* isolate,
+  const char*,
+  value_tag<complex_tag<Eina_Hash *, T, U...>> tag,
+  bool throw_js_exception = true)
+{
+  if (throw_js_exception)
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Not implemented yet")));
+  throw std::logic_error("");
+}
+
+template <typename T, typename...U>
+inline const Eina_Hash* get_value_from_javascript(
+  v8::Local<v8::Value> v,
+  v8::Isolate* isolate,
+  const char* class_name,
+  value_tag<complex_tag<const Eina_Hash *, T, U...>>,
+  bool throw_js_exception = true)
+{
+  return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_Hash *, T, U...>>{}, throw_js_exception);
+}
+
+template <typename...I>
+inline Eina_List* get_value_from_javascript(
+  v8::Local<v8::Value> v,
+  v8::Isolate* isolate,
+  const char*,
+  value_tag<complex_tag<Eina_List *, I...>> /*tag*/,
+  bool throw_js_exception = true)
+{
+  if(v->IsNull())
+    return nullptr;
+  else if(v->IsObject())
+    {
+      v8::Local<v8::Object> object = v->ToObject();
+      if(object->InternalFieldCount() == 1)
+        {
+           eina_container_base* cbase = compatibility_get_pointer_internal_field<eina_container_base*>(object, 0);
+           return static_cast<Eina_List*>(cbase->get_container_native_handle());
+        }
+    }
+  if (throw_js_exception)
+    eina::js::compatibility_throw
+      (isolate, v8::Exception::TypeError
+       (eina::js::compatibility_new<v8::String>(isolate, "Type expected is different. Expected Eolian list type")));
+  throw std::logic_error("");
+  return nullptr;
+}
+
+template <typename...I>
+inline const Eina_List* get_value_from_javascript(
+  v8::Local<v8::Value> v,
+  v8::Isolate* isolate,
+  const char* class_name,
+  value_tag<complex_tag<const Eina_List *, I...>>,
+  bool throw_js_exception = true)
+{
+  return get_value_from_javascript(v, isolate, class_name, value_tag<complex_tag<Eina_List *, I...>>{}, throw_js_exception);
+}
+
+inline const void* get_value_from_javascript
+  (v8::Local<v8::Value>,
+   v8::Isolate*,
+   const char*,
+   value_tag<const void *>)
+{
+  return nullptr;
+}
+
+
+typedef void (*Evas_Smart_Cb)(void*, _Eo_Opaque*, void*);
+
+inline Evas_Smart_Cb get_value_from_javascript (
+  v8::Local<v8::Value>,
+  v8::Isolate*,
+  const char*,
+  value_tag<Evas_Smart_Cb>)
+{
+  return nullptr;
+}
+
+} } }
+
+#endif
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
new file mode 100644 (file)
index 0000000..655b1b1
--- /dev/null
@@ -0,0 +1,261 @@
+#ifndef EFL_EINA_JS_GET_VALUE_FROM_C_HH
+#define EFL_EINA_JS_GET_VALUE_FROM_C_HH
+
+#include <eina_js_compatibility.hh>
+
+#include <type_traits>
+#include <cstdlib>
+#include <typeinfo>
+#include <memory>
+
+namespace efl { namespace eina { namespace js {
+
+template <typename T> struct print_tag {};
+
+template <typename T>
+inline v8::Local<v8::Value>
+get_value_from_c(T v, v8::Isolate* isolate, const char*
+                 , typename std::enable_if<std::is_integral<typename std::remove_reference<T>::type>::value && !std::is_same<T, Eina_Bool>::value>::type* = 0)
+{
+  return eina::js::compatibility_new<v8::Integer>(isolate, v);
+}
+
+template <typename T>
+inline v8::Local<v8::Value>
+get_value_from_c(T v, v8::Isolate* isolate, const char*
+                 , typename std::enable_if<std::is_enum<typename std::remove_reference<T>::type>::value>::type* = 0)
+{
+  return eina::js::compatibility_new<v8::Integer>(isolate, v);
+}
+
+template <typename T>
+inline v8::Local<v8::Value>
+get_value_from_c(T v, v8::Isolate* isolate, const char*
+                 , typename std::enable_if<std::is_same<typename std::remove_reference<T>::type, Eina_Bool>::value>::type* = 0)
+{
+  return eina::js::compatibility_new<v8::Boolean>(isolate, v);
+}
+
+template <typename T>
+inline v8::Local<T>
+get_value_from_c(v8::Local<T> v, v8::Isolate*, const char*)
+{
+  return v;
+}
+
+template <typename T>
+inline v8::Local<v8::Value>
+get_value_from_c(T v, v8::Isolate* isolate, const char*
+                 , typename std::enable_if<std::is_floating_point<typename std::remove_reference<T>::type>::value>::type* = 0)
+{
+  return eina::js::compatibility_new<v8::Number>(isolate, v);
+}
+
+inline v8::Local<v8::Value>
+get_value_from_c(const char* v, v8::Isolate* isolate, const char*)
+{
+  if (!v)
+    return v8::Null(isolate);
+
+  return eina::js::compatibility_new<v8::String>(isolate, v);
+}
+
+inline v8::Local<v8::Value>
+get_value_from_c(char* v, v8::Isolate* isolate, const char* class_name)
+{
+  return js::get_value_from_c(const_cast<const char*>(v), isolate, class_name);
+}
+
+inline v8::Local<v8::Value>
+get_value_from_c(void*, v8::Isolate*, const char*)
+{
+  // TODO: create Extern?
+  std::cerr << "aborting because we don't know the type void*" << std::endl;
+  std::abort();
+}
+
+inline v8::Local<v8::Value>
+get_value_from_c(const void*, v8::Isolate*, const char*)
+{
+  // TODO: create Extern?
+  std::cerr << "aborting because we don't know the type void*" << std::endl;
+  std::abort();
+}
+
+// For function pointer types
+template <typename T>
+inline v8::Local<v8::Value>
+get_value_from_c(T, v8::Isolate*, const char*
+                 , typename std::enable_if
+                 <std::is_pointer<typename std::remove_reference<T>::type>::value
+                 && std::is_function<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value
+                 >::type* = 0)
+{
+  // TODO: create Extern?
+  std::cerr << "aborting because we don't know the type " << typeid(print_tag<T>).name() << std::endl;
+  std::abort();
+}
+
+// For all non-pointer types that are not handled
+template <typename T>
+inline v8::Local<v8::Value>
+get_value_from_c(T, v8::Isolate*, const char*
+                 , typename std::enable_if
+                 <!std::is_pointer<typename std::remove_reference<T>::type>::value
+                 && !std::is_integral<typename std::remove_reference<T>::type>::value
+                 && !std::is_floating_point<typename std::remove_reference<T>::type>::value
+                 && !std::is_enum<typename std::remove_reference<T>::type>::value
+                 && !std::is_same<typename std::remove_reference<T>::type, Eina_Bool>::value
+                 && !js::is_struct_tag<typename std::remove_reference<T>::type>::value
+                 && !js::is_struct_ptr_tag<typename std::remove_reference<T>::type>::value
+                 && !js::is_complex_tag<typename std::remove_reference<T>::type>::value
+                 >::type* = 0)
+{
+  std::cerr << "aborting because we don't know the type " << typeid(print_tag<T>).name() << std::endl;
+  std::abort();
+}
+
+// For all non-handled pointer types (which are not function pointers):
+// - we try to dereference it in the SFINAE
+// - if it matches we call get_value_from_c for the dereferenced type
+// - if it fails (probably because it is opaque) the void* or const void*
+//   overload will take place (implicit conversion)
+template <typename T>
+inline auto
+get_value_from_c(T object, v8::Isolate* isolate, const char* class_name
+                 , typename std::enable_if<
+                   (std::is_pointer<typename std::remove_reference<T>::type>::value
+                    && !std::is_function<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value
+                   )
+                   && !(std::is_same<typename std::remove_reference<T>::type, char*>::value ||
+                        std::is_same<typename std::remove_reference<T>::type, const char*>::value ||
+                        std::is_same<typename std::remove_reference<T>::type, void*>::value ||
+                        std::is_same<typename std::remove_reference<T>::type, const void*>::value ||
+                        std::is_same<typename std::remove_reference<T>::type, Eo*>::value ||
+                        std::is_same<typename std::remove_reference<T>::type, const Eo*>::value
+                   )>::type* = 0) -> decltype(get_value_from_c(*object, isolate, class_name))
+{
+  std::cerr << "dereferencing " << typeid(print_tag<T>).name() << std::endl;
+  return get_value_from_c(*object, isolate, class_name);
+}
+
+inline v8::Local<v8::Value>
+get_value_from_c(Eo* v, v8::Isolate* isolate, const char* class_name)
+{
+  auto ctor = ::efl::eina::js::get_class_constructor(class_name);
+  return new_v8_external_instance(ctor, v, isolate);
+}
+
+inline v8::Local<v8::Value>
+get_value_from_c(const Eo* v, v8::Isolate* isolate, const char* class_name)
+{
+  // TODO: implement const objects?
+  auto ctor = ::efl::eina::js::get_class_constructor(class_name);
+  return new_v8_external_instance(ctor, const_cast<Eo*>(v), isolate);
+}
+
+template <typename T>
+inline v8::Local<v8::Value>
+get_value_from_c(struct_ptr_tag<T> v, v8::Isolate* isolate, const char* class_name)
+{
+  // TODO: implement const structs?
+  auto ctor = ::efl::eina::js::get_class_constructor(class_name);
+  return new_v8_external_instance(ctor, const_cast<typename std::remove_const<T>::type>(v.value), isolate);
+}
+
+template <typename T>
+inline v8::Local<v8::Value>
+get_value_from_c(struct_tag<T> v, v8::Isolate* isolate, const char* class_name)
+{
+  return get_value_from_c(struct_ptr_tag<T*>{new T(v.value)}, isolate, class_name);
+}
+
+template <typename T, typename K>
+inline v8::Local<v8::Value>
+get_value_from_c(efl::eina::js::complex_tag<Eina_Accessor *, T, K> v, v8::Isolate* isolate, const char*)
+{
+  using wrapped_type = typename container_wrapper<T>::type;
+  auto a = new ::efl::eina::accessor<wrapped_type>{v.value};
+  return export_accessor<T>(*a , isolate, K::class_name());
+}
+
+template <typename T, typename K>
+inline v8::Local<v8::Value>
+get_value_from_c(efl::eina::js::complex_tag<const Eina_Accessor *, T, K> v, v8::Isolate* isolate, const char* class_name)
+{
+  // TODO implement const accessor?
+  return get_value_from_c(efl::eina::js::complex_tag<Eina_Accessor*, T, K>{const_cast<Eina_Accessor*>(v.value)}, isolate, class_name);
+}
+
+template <typename T, typename K>
+inline v8::Local<v8::Value>
+get_value_from_c(efl::eina::js::complex_tag<Eina_Array *, T, K> v, v8::Isolate* isolate, const char*)
+{
+  // TODO: use unique_ptr for eina_array to avoid leak ?
+  auto o = new ::efl::eina::js::range_eina_array<T, K>(v.value);
+  auto ctor = get_array_instance_template();
+  return new_v8_external_instance(ctor, o, isolate);
+}
+
+template <typename T, typename K>
+inline v8::Local<v8::Value>
+get_value_from_c(efl::eina::js::complex_tag<const Eina_Array *, T, K> v, v8::Isolate* isolate, const char* class_name)
+{
+  // TODO: implement const array?
+  return get_value_from_c(efl::eina::js::complex_tag<Eina_Array *, T, K>{const_cast<Eina_Array*>(v.value)}, isolate, class_name);
+}
+
+template <typename T, typename K>
+inline v8::Local<v8::Value>
+get_value_from_c(efl::eina::js::complex_tag<Eina_Iterator *, T, K>, v8::Isolate*, const char*)
+{
+  std::cerr << "get_value_from_c for Eina_Iterator not implemented. Aborting..." << std::endl;
+  std::abort();
+}
+
+template <typename T, typename K>
+inline v8::Local<v8::Value>
+get_value_from_c(efl::eina::js::complex_tag<const Eina_Iterator *, T, K>, v8::Isolate*, const char*)
+{
+  std::cerr << "get_value_from_c for Eina_Iterator not implemented. Aborting..." << std::endl;
+  std::abort();
+}
+
+template <typename T, typename U, typename K>
+inline v8::Local<v8::Value>
+get_value_from_c(efl::eina::js::complex_tag<Eina_Hash *, T, U, K>, v8::Isolate*, const char*)
+{
+  std::cerr << "get_value_from_c for Eina_Hash not implemented. Aborting..." << std::endl;
+  std::abort();
+}
+
+template <typename T, typename U, typename K>
+inline v8::Local<v8::Value>
+get_value_from_c(efl::eina::js::complex_tag<const Eina_Hash *, T, U, K>, v8::Isolate*, const char*)
+{
+  std::cerr << "get_value_from_c for Eina_Hash not implemented. Aborting..." << std::endl;
+  std::abort();
+}
+
+template <typename T, typename K>
+inline v8::Local<v8::Value>
+get_value_from_c(efl::eina::js::complex_tag<Eina_List *, T, K> v, v8::Isolate* isolate, const char*)
+{
+  // TODO: ensure eina_list ownership ???
+  auto o = new ::efl::eina::js::range_eina_list<T, K>(v.value);
+  auto ctor = get_list_instance_template();
+  return new_v8_external_instance(ctor, o, isolate);
+}
+
+template <typename T, typename K>
+inline v8::Local<v8::Value>
+get_value_from_c(efl::eina::js::complex_tag<const Eina_List *, T, K> v, v8::Isolate* isolate, const char* class_name)
+{
+  // TODO: implement const list?
+  return get_value_from_c(efl::eina::js::complex_tag<Eina_List *, T, K>{const_cast<Eina_List*>(v.value)}, isolate, class_name);
+}
+
+
+} } }
+
+#endif
diff --git a/src/bindings/js/eina_js/eina_js_iterator.cc b/src/bindings/js/eina_js/eina_js_iterator.cc
new file mode 100644 (file)
index 0000000..d2480b8
--- /dev/null
@@ -0,0 +1,32 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eina.hh>
+#include <Eina_Js.hh>
+
+namespace efl { namespace eina { namespace js {
+
+EAPI
+void register_destroy_iterator(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    typedef void (*deleter_t)(void*);
+
+    auto f = [](compatibility_callback_info_type info) -> compatibility_return_type
+      {
+        if (info.Length() != 1 || !info[0]->IsObject())
+          return compatibility_return();
+
+        v8::Handle<v8::Object> o = info[0]->ToObject();
+
+        deleter_t deleter = compatibility_get_pointer_internal_field<deleter_t>(o, 1);
+        deleter(compatibility_get_pointer_internal_field<>(o, 0));
+        return compatibility_return();
+      };
+
+    global->Set(name, compatibility_new<v8::FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+} } } // namespace efl { namespace js {
diff --git a/src/bindings/js/eina_js/eina_js_iterator.hh b/src/bindings/js/eina_js/eina_js_iterator.hh
new file mode 100644 (file)
index 0000000..ed0066b
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef EINA_JS_ITERATOR_HH
+#define EINA_JS_ITERATOR_HH
+
+#include <type_traits>
+
+#include <eina_js_value.hh>
+
+namespace efl { namespace eina { namespace js {
+
+/* Exports the \p iterator to be manipulated by the JS code. The iterator should
+   remain alive as long as there is JS code referencing it. The JS code is able
+   to destroy the iterator by itself if you register the appropriate function
+   through `register_destroy_iterator`.
+
+   The exported JS object models part the [iterator concept from ECMAScript
+   6](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol).
+
+   The iterator will have the `next` function, but the returned object won't
+   have a `done` attribute, because the eina_iterator itself doesn't expose this
+   information.*/
+template<class T>
+v8::Local<v8::Object> export_iterator(::efl::eina::iterator<T> *i,
+                                      v8::Isolate *isolate)
+{
+    typedef ::efl::eina::iterator<T> value_type;
+    typedef value_type *ptr_type;
+    typedef void (*deleter_t)(void*);
+
+    auto obj_tpl = compatibility_new<v8::ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(2);
+
+    auto ret = obj_tpl->NewInstance();
+
+    auto next = [](js::compatibility_callback_info_type info) -> compatibility_return_type
+      {
+        if (info.Length() != 0)
+          return compatibility_return();
+
+        void *ptr = compatibility_get_pointer_internal_field(info.This(), 0);
+        auto &value = *static_cast<ptr_type>(ptr);
+        v8::Local<v8::Object> o = compatibility_new<v8::Object>(info.GetIsolate());
+        o->Set(compatibility_new<v8::String>(info.GetIsolate(), "value"),
+               value_cast<v8::Local<v8::Value>>(*value, info.GetIsolate()));
+        ++value;
+        return compatibility_return(o, info);
+      };
+
+    ret->Set(compatibility_new<v8::String>(isolate, "next"),
+             compatibility_new<v8::FunctionTemplate>(isolate, next)->GetFunction());
+
+    {
+        deleter_t deleter = [](void *i) {
+            delete static_cast<ptr_type>(i);
+        };
+        compatibility_set_pointer_internal_field(ret, 0, i);
+        compatibility_set_pointer_internal_field
+          (ret, 1, reinterpret_cast<void*>(deleter));
+    }
+
+    return ret;
+}
+
+/* Extracts and returns a copy from the internal iterator object from the JS
+   object. */
+template<class T>
+::efl::eina::iterator<T> *import_iterator(v8::Handle<v8::Object> o)
+  ;
+// {
+//     typedef ::efl::eina::iterator<T> value_type;
+//     typedef value_type *ptr_type;
+
+//     return reinterpret_cast<ptr_type>(o->GetAlignedPointerFromInternalField(0));
+// }
+
+void register_destroy_iterator(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name);
+
+} } } // namespace efl::js
+
+#endif /* EINA_JS_ITERATOR_HH */
diff --git a/src/bindings/js/eina_js/eina_js_list.hh b/src/bindings/js/eina_js/eina_js_list.hh
new file mode 100644 (file)
index 0000000..6ab0521
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef EINA_JS_LIST_HH
+#define EINA_JS_LIST_HH
+
+#include <iostream>
+
+#include <eina_js_container.hh>
+#include <eina_js_compatibility.hh>
+
+#include <iterator>
+
+namespace efl { namespace eina { namespace js {
+
+template <typename T, typename K, typename W>
+struct eina_list : eina_container_common<efl::eina::list
+                                    <W
+                                    , typename std::conditional
+                                      <std::is_base_of<efl::eo::concrete, W>::value
+                                       , efl::eina::eo_clone_allocator
+                                       , efl::eina::malloc_clone_allocator
+                                       >::type>, T, K>
+{
+  typedef eina_container_common<efl::eina::list<W
+                           , typename std::conditional
+                           <std::is_base_of<efl::eo::concrete, W>::value
+                            , efl::eina::eo_clone_allocator
+                            , efl::eina::malloc_clone_allocator
+                            >::type>, T, K> base_type;
+  using base_type::base_type;
+  typedef typename base_type::container_type container_type;
+
+  eina_container_base* concat(eina_container_base const& other) const
+  {
+    return detail::concat(*this, other);
+  }
+  eina_container_base* slice(std::int64_t i, std::int64_t j) const
+  {
+    return detail::slice(*this, i, j);
+  }
+  v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t index, v8::Local<v8::Value> v)
+  {
+    return detail::set<T,W>(isolate, *this, index, v);
+  }
+  int push(v8::Isolate* isolate, v8::Local<v8::Value> v)
+  {
+    return detail::push<T,W>(isolate, *this, v);
+  }
+  v8::Local<v8::Value> pop(v8::Isolate* isolate)
+  {
+    return detail::pop<T,W,K>(isolate, *this);
+  }
+  js::container_type get_container_type() const { return list_container_type; }
+};
+
+template <typename T, typename K, typename W>
+struct range_eina_list : eina_container_common<typename efl::eina::range_list<W>, T, K>
+{
+  typedef eina_container_common<efl::eina::range_list<W>, T, K> base_type;
+  using base_type::base_type;
+  typedef typename base_type::container_type container_type;
+  typedef typename std::conditional
+    <std::is_base_of<efl::eo::concrete, W>::value
+     , efl::eina::eo_clone_allocator
+     , efl::eina::malloc_clone_allocator
+     >::type clone_allocator_type;
+  
+  eina_container_base* concat(eina_container_base const& other) const
+  {
+    range_eina_list<T, K, W>const& rhs = static_cast<range_eina_list<T, K, W>const&>(other);
+    efl::eina::list<W, clone_allocator_type>
+      list(this->_container.begin(), this->_container.end());
+    list.insert(list.end(), rhs._container.begin(), rhs._container.end());
+    return new eina::js::eina_list<T, K, W>(list.release_native_handle());
+  }
+  eina_container_base* slice(std::int64_t i, std::int64_t j) const
+  {
+    efl::eina::list<W, clone_allocator_type>
+      list(std::next(this->_container.begin(), i), std::next(this->_container.begin(), j));
+    return new eina::js::eina_list<T, K, W>(list.release_native_handle());
+  }
+  v8::Local<v8::Value> set(v8::Isolate* isolate, std::size_t, v8::Local<v8::Value>)
+  {
+    return v8::Undefined(isolate);
+  }
+  int push(v8::Isolate*, v8::Local<v8::Value>)
+  {
+    return this->size();
+  }
+  v8::Local<v8::Value> pop(v8::Isolate* isolate)
+  {
+    return v8::Undefined(isolate);
+  }
+  js::container_type get_container_type() const { return list_container_type; }
+};
+
+// Problematic types.
+template <>
+struct eina_list<_Elm_Calendar_Mark*, js::nonclass_cls_name_getter, _Elm_Calendar_Mark>
+  : empty_container_base
+{ eina_list(Eina_List const*){} };
+template <>
+struct eina_list<Elm_Gen_Item*, js::nonclass_cls_name_getter, Elm_Gen_Item>
+  : empty_container_base
+{ eina_list(Eina_List const*){} };
+template <>
+struct eina_list<_Evas_Textblock_Rectangle*, js::nonclass_cls_name_getter, _Evas_Textblock_Rectangle>
+  : empty_container_base
+{ eina_list(Eina_List const*){} };
+template <>
+struct eina_list<_Elm_Map_Overlay*, js::nonclass_cls_name_getter, _Elm_Map_Overlay>
+  : empty_container_base
+{ eina_list(Eina_List const*){} };
+
+template <>
+struct range_eina_list<_Elm_Calendar_Mark*, js::nonclass_cls_name_getter, _Elm_Calendar_Mark>
+  : empty_container_base
+{ range_eina_list(Eina_List const*){} };
+template <>
+struct range_eina_list<Elm_Gen_Item*, js::nonclass_cls_name_getter, Elm_Gen_Item>
+  : empty_container_base
+{ range_eina_list(Eina_List const*){} };
+template <>
+struct range_eina_list<_Evas_Textblock_Rectangle*, js::nonclass_cls_name_getter, _Evas_Textblock_Rectangle>
+  : empty_container_base
+{ range_eina_list(Eina_List const*){} };
+template <>
+struct range_eina_list<_Elm_Map_Overlay*, js::nonclass_cls_name_getter, _Elm_Map_Overlay>
+  : empty_container_base
+{ range_eina_list(Eina_List const*){} };
+
+} } }
+
+#endif
diff --git a/src/bindings/js/eina_js/eina_js_log.cc b/src/bindings/js/eina_js/eina_js_log.cc
new file mode 100644 (file)
index 0000000..415a827
--- /dev/null
@@ -0,0 +1,742 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string>
+#include <map>
+#include <Eina_Js.hh>
+
+namespace efl { namespace eina { namespace js {
+
+v8::Local<v8::String> to_v8_string(v8::Isolate *isolate, const char *fmt,
+                                   va_list args)
+{
+    using v8::String;
+#if 0
+    /* TODO: unfortunately, the elegant and exception-safe version isn't
+       compiling (yet!) */
+    efl::eina::stringshare s(eina_stringshare_vprintf(fmt, args),
+                             efl::eina::steal_stringshare_ref);
+    return compatibility_new<String>(isolate, s.data(), String::kNormalString,
+                                     s.size());
+#else
+    auto s = eina_stringshare_vprintf(fmt, args);
+    auto ret = compatibility_new<String>(isolate, s);
+    eina_stringshare_del(s);
+    return ret;
+#endif
+}
+
+static global_ref<v8::Value> js_eina_log_print_cb_data;
+static std::map<int, std::string> js_eina_log_color_map;
+
+static void js_eina_log_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level,
+                                 const char *file, const char *fnc, int line,
+                                 const char *fmt, void */*data*/, va_list args)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::Isolate;
+
+    Isolate *const isolate = Isolate::GetCurrent();
+    constexpr unsigned argc = 7;
+
+    v8::Handle<v8::Value> argv[argc] = {
+        compatibility_new<String>(isolate, d->name ? d->name : ""),
+        compatibility_new<String>(isolate, d->color ? d->color : ""),
+        compatibility_new<Integer>(isolate, static_cast<int>(level)),
+        compatibility_new<String>(isolate, file),
+        compatibility_new<String>(isolate, fnc),
+        compatibility_new<Integer>(isolate, line),
+        to_v8_string(isolate, fmt, args)
+    };
+
+    auto o = js_eina_log_print_cb_data.handle();
+    v8::Function::Cast(*o)->Call(o->ToObject(), argc, argv);
+}
+
+static bool valid_level_conversion(int src, Eina_Log_Level &dst)
+{
+    if (src != EINA_LOG_LEVEL_CRITICAL && src != EINA_LOG_LEVEL_ERR
+        && src != EINA_LOG_LEVEL_WARN && src != EINA_LOG_LEVEL_INFO
+        && src != EINA_LOG_LEVEL_DBG)
+        return false;
+
+    dst = static_cast<Eina_Log_Level>(src);
+    return true;
+}
+
+EAPI
+void register_log_print(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                        v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::String;
+    using v8::StackTrace;
+    using v8::FunctionTemplate;
+
+    auto print = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 3 || !args[0]->IsNumber() || !args[1]->IsNumber()
+            || !args[2]->IsString())
+            return compatibility_return();
+
+        Eina_Log_Level level;
+        if (!valid_level_conversion(args[1]->NumberValue(), level))
+            return compatibility_return();
+
+        auto frame = compatibility_current_stack_trace<>(args.GetIsolate(), 1,
+                             StackTrace::kDetailed)->GetFrame(0);
+
+        eina_log_print(args[0]->NumberValue(), level,
+                       *String::Utf8Value(frame->GetScriptNameOrSourceURL()),
+                       *String::Utf8Value(frame->GetFunctionName()),
+                       frame->GetLineNumber(), "%s",
+                       *String::Utf8Value(args[2]));
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, print)
+                ->GetFunction());
+}
+
+EAPI
+void register_log_domain_register(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::Local;
+    using v8::String;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString())
+            return compatibility_return();
+
+        // We duplicate the color string as eina takes a const char* but does take care of 
+        // its lifetime, assuming a ever lasting string.
+        std::string color = *String::Utf8Value(args[1]);
+        int d = eina_log_domain_register(*String::Utf8Value(args[0]),
+                                         color.c_str());
+        js_eina_log_color_map[d] = color;
+
+        auto isolate = args.GetIsolate();
+        return compatibility_return(value_cast<Local<Value>>(d, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_domain_unregister(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        int domain = args[0]->NumberValue();
+        eina_log_domain_unregister(domain);
+        js_eina_log_color_map.erase(domain);
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_domain_registered_level_get(v8::Isolate *isolate,
+                                              v8::Handle<v8::Object> global,
+                                              v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::Local;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        int l = eina_log_domain_registered_level_get(args[0]->NumberValue());
+        auto isolate = args.GetIsolate();
+        return compatibility_return(value_cast<Local<Value>>(l, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_domain_registered_level_set(v8::Isolate *isolate,
+                                              v8::Handle<v8::Object> global,
+                                              v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 2 || !args[0]->IsNumber() || !args[1]->IsNumber())
+            return compatibility_return();
+
+        eina_log_domain_registered_level_set(args[0]->NumberValue(),
+                                             args[1]->NumberValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_print_cb_set(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        js_eina_log_print_cb_data
+          = global_ref<v8::Value>(args.GetIsolate(), args[0]);
+        eina_log_print_cb_set(js_eina_log_print_cb, NULL);
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_level_set(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                            v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        eina_log_level_set(args[0]->NumberValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_level_get(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                            v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+    using v8::Integer;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        int l = eina_log_level_get();
+        auto ret = compatibility_new<Integer>(args.GetIsolate(), l);
+        return compatibility_return(ret, args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_level_check(v8::Isolate *isolate,
+                              v8::Handle<v8::Object> global,
+                              v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+    using v8::Boolean;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        bool b = eina_log_level_check(args[0]->NumberValue());
+        auto ret = compatibility_new<Boolean>(args.GetIsolate(), b);
+        return compatibility_return(ret, args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_color_disable_set(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsBoolean())
+            return compatibility_return();
+
+        eina_log_color_disable_set(args[0]->BooleanValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_color_disable_get(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::Boolean;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        bool b = eina_log_color_disable_get();
+        auto ret = compatibility_new<Boolean>(args.GetIsolate(), b);
+        return compatibility_return(ret, args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_file_disable_set(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsBoolean())
+            return compatibility_return();
+
+        eina_log_file_disable_set(args[0]->BooleanValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_file_disable_get(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::Boolean;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        bool b = eina_log_file_disable_get();
+        auto ret = compatibility_new<Boolean>(args.GetIsolate(), b);
+        return compatibility_return(ret, args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_function_disable_set(v8::Isolate *isolate,
+                                       v8::Handle<v8::Object> global,
+                                       v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsBoolean())
+            return compatibility_return();
+
+        eina_log_function_disable_set(args[0]->BooleanValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_function_disable_get(v8::Isolate *isolate,
+                                       v8::Handle<v8::Object> global,
+                                       v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::Boolean;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        bool b = eina_log_function_disable_get();
+        auto ret = compatibility_new<Boolean>(args.GetIsolate(), b);
+        return compatibility_return(ret, args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_abort_on_critical_set(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsBoolean())
+            return compatibility_return();
+
+        eina_log_abort_on_critical_set(args[0]->BooleanValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_abort_on_critical_get(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::Boolean;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        bool b = eina_log_abort_on_critical_get();
+        auto ret = compatibility_new<Boolean>(args.GetIsolate(), b);
+        return compatibility_return(ret, args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_abort_on_critical_level_set(v8::Isolate *isolate,
+                                              v8::Handle<v8::Object> global,
+                                              v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        eina_log_abort_on_critical_level_set(args[0]->NumberValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_abort_on_critical_level_get(v8::Isolate *isolate,
+                                              v8::Handle<v8::Object> global,
+                                              v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+    using v8::Integer;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        int l = eina_log_abort_on_critical_level_get();
+        auto ret = compatibility_new<Integer>(args.GetIsolate(), l);
+        return compatibility_return(ret, args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_domain_level_set(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+    using v8::String;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsNumber())
+            return compatibility_return();
+
+        eina_log_domain_level_set(*String::Utf8Value(args[0]),
+                                  args[1]->NumberValue());
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_domain_level_get(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+    using v8::String;
+    using v8::Integer;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsString())
+            return compatibility_return();
+
+        int l = eina_log_domain_level_get(*String::Utf8Value(args[0]));
+        auto ret = compatibility_new<Integer>(args.GetIsolate(), l);
+        return compatibility_return(ret, args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_log_timing(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                         v8::Handle<v8::String> name)
+{
+    using v8::Value;
+    using v8::FunctionTemplate;
+    using v8::String;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 3 || !args[0]->IsNumber() || !args[1]->IsNumber()
+            || !args[2]->IsString()) {
+            return compatibility_return();
+        }
+
+        eina_log_timing(args[0]->NumberValue(),
+                        static_cast<Eina_Log_State>(args[1]->NumberValue()),
+                        *String::Utf8Value(args[2]));
+        return compatibility_return();
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+static void register_constant(v8::Isolate *isolate, v8::Handle<v8::Object> global, int value, const char* name)
+{
+    global->Set(compatibility_new<v8::String>(isolate, name), compatibility_new<v8::Integer>(isolate, value));
+}
+
+static void register_constant(v8::Isolate *isolate, v8::Handle<v8::Object> global, const char* value, const char* name)
+{
+    global->Set(compatibility_new<v8::String>(isolate, name), compatibility_new<v8::String>(isolate, value));
+}
+
+EAPI void register_log_constants(v8::Isolate *isolate, v8::Handle<v8::Object> global)
+{
+    register_constant(isolate, global, EINA_LOG_STATE_START, "LOG_STATE_START");
+    register_constant(isolate, global, EINA_LOG_STATE_START, "LOG_STATE_STOP");
+
+    register_constant(isolate, global, EINA_LOG_LEVEL_CRITICAL, "LOG_LEVEL_CRITICAL");
+    register_constant(isolate, global, EINA_LOG_LEVEL_ERR, "LOG_LEVEL_ERR");
+    register_constant(isolate, global, EINA_LOG_LEVEL_WARN, "LOG_LEVEL_WARN");
+    register_constant(isolate, global, EINA_LOG_LEVEL_INFO, "LOG_LEVEL_INFO");
+    register_constant(isolate, global, EINA_LOG_LEVEL_DBG, "LOG_LEVEL_DBG");
+    register_constant(isolate, global, EINA_LOG_LEVELS, "LOG_LEVELS");
+    register_constant(isolate, global, EINA_LOG_LEVEL_UNKNOWN, "LOG_LEVEL_UNKNOWN");
+
+    register_constant(isolate, global, EINA_LOG_DOMAIN_GLOBAL, "LOG_DOMAIN_GLOBAL");
+
+    register_constant(isolate, global, EINA_COLOR_LIGHTRED, "COLOR_LIGHTRED");
+    register_constant(isolate, global, EINA_COLOR_RED, "COLOR_RED");
+    register_constant(isolate, global, EINA_COLOR_LIGHTBLUE, "COLOR_LIGHTBLUE");
+    register_constant(isolate, global, EINA_COLOR_BLUE, "COLOR_BLUE");
+    register_constant(isolate, global, EINA_COLOR_GREEN, "COLOR_GREEN");
+    register_constant(isolate, global, EINA_COLOR_YELLOW, "COLOR_YELLOW");
+    register_constant(isolate, global, EINA_COLOR_ORANGE, "COLOR_ORANGE");
+    register_constant(isolate, global, EINA_COLOR_WHITE, "COLOR_WHITE");
+    register_constant(isolate, global, EINA_COLOR_LIGHTCYAN, "COLOR_LIGHTCYAN");
+    register_constant(isolate, global, EINA_COLOR_CYAN, "COLOR_CYAN");
+    register_constant(isolate, global, EINA_COLOR_RESET, "COLOR_RESET");
+    register_constant(isolate, global, EINA_COLOR_HIGH, "COLOR_HIGH");
+}
+
+
+#define REGISTER_LOG_HELPER(isolate, global, level, name) \
+{ \
+    using v8::String; \
+    using v8::FunctionTemplate;\
+    using v8::StackTrace;\
+\
+    auto wrapper = [](compatibility_callback_info_type args)\
+        -> compatibility_return_type {\
+        if (args.Length() != 1 || !args[0]->IsString()) {\
+            eina::js::compatibility_throw \
+                (args.GetIsolate(), v8::Exception::TypeError(\
+                                        eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Message must be a string."))); \
+            return compatibility_return();\
+        } \
+\
+        auto frame = compatibility_current_stack_trace<>(args.GetIsolate(), 1,\
+                             StackTrace::kDetailed)->GetFrame(0);\
+\
+        eina_log_print(EINA_LOG_DOMAIN_GLOBAL, level,\
+                       *String::Utf8Value(frame->GetScriptNameOrSourceURL()),\
+                       *String::Utf8Value(frame->GetFunctionName()),\
+                       frame->GetLineNumber(), "%s",\
+                       *String::Utf8Value(args[0]));\
+\
+        return compatibility_return();\
+    };\
+\
+    global->Set(compatibility_new<String>(isolate, name),\
+                compatibility_new<FunctionTemplate>(isolate, wrapper)->GetFunction());\
+}
+
+EAPI void register_log_helpers(v8::Isolate *isolate, v8::Handle<v8::Object> global)
+{
+    REGISTER_LOG_HELPER(isolate, global, EINA_LOG_LEVEL_CRITICAL, "logCritical");
+    REGISTER_LOG_HELPER(isolate, global, EINA_LOG_LEVEL_ERR, "logError");
+    REGISTER_LOG_HELPER(isolate, global, EINA_LOG_LEVEL_WARN, "logWarning");
+    REGISTER_LOG_HELPER(isolate, global, EINA_LOG_LEVEL_INFO, "logInfo");
+    REGISTER_LOG_HELPER(isolate, global, EINA_LOG_LEVEL_DBG, "logDebug");
+}
+
+} } } // namespace efl { namespace js {
+
+EAPI
+void eina_log_register(v8::Handle<v8::Object> exports, v8::Isolate* isolate)
+{
+    using efl::eina::js::compatibility_new;
+
+    efl::eina::js::register_log_domain_register(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "registerLogDomain"));
+    efl::eina::js::register_log_domain_unregister(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "unregisterLogDomain"));
+    efl::eina::js::register_log_domain_registered_level_set(isolate, exports
+                                             , compatibility_new<v8::String>(isolate, "setLogDomainRegisteredLevel"));
+    efl::eina::js::register_log_domain_registered_level_get(isolate, exports
+                                             , compatibility_new<v8::String>(isolate, "getLogDomainRegisteredLevel"));
+
+    efl::eina::js::register_log_print(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "logPrint"
+));
+    efl::eina::js::register_log_print_cb_set(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "setLogPrintCb"
+));
+
+    efl::eina::js::register_log_level_set(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "setLogLevel"
+));
+    efl::eina::js::register_log_level_get(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "getLogLevel"
+));
+    efl::eina::js::register_log_level_check(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "checkLogLevel"
+));
+
+    efl::eina::js::register_log_color_disable_set(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "setLogColorDisable"
+));
+    efl::eina::js::register_log_color_disable_get(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "getLogColorDisable"
+));
+
+    efl::eina::js::register_log_file_disable_set(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "setLogFileDisable"
+));
+    efl::eina::js::register_log_file_disable_get(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "getLogFileDisable"
+));
+
+    efl::eina::js::register_log_function_disable_set(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "setLogFunctionDisable"
+));
+    efl::eina::js::register_log_function_disable_get(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "getLogFunctionDisable"
+));
+
+    efl::eina::js::register_log_abort_on_critical_set(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "setLogAbortOnCritical"
+));
+    efl::eina::js::register_log_abort_on_critical_get(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "getLogAbortOnCritical"
+));
+    efl::eina::js::register_log_abort_on_critical_level_set(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "setLogAbortOnCriticalLevel"
+));
+    efl::eina::js::register_log_abort_on_critical_level_get(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "getLogAbortOnCriticalLevel"
+));
+
+    efl::eina::js::register_log_domain_level_set(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "setLogDomainLevel"
+));
+    efl::eina::js::register_log_domain_level_get(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "getLogDomainLevel"
+));
+
+    efl::eina::js::register_log_timing(isolate, exports
+                                            , compatibility_new<v8::String>(isolate, "logTiming"));
+
+    efl::eina::js::register_log_constants(isolate, exports);
+
+    efl::eina::js::register_log_helpers(isolate, exports);
+}
diff --git a/src/bindings/js/eina_js/eina_js_log.hh b/src/bindings/js/eina_js/eina_js_log.hh
new file mode 100644 (file)
index 0000000..bed5a1b
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef EINA_JS_LOG_HH
+#define EINA_JS_LOG_HH
+
+#include <type_traits>
+
+namespace efl { namespace eina { namespace js {
+
+using ::efl::eina::js::compatibility_new;
+using ::efl::eina::js::compatibility_return_type;
+using ::efl::eina::js::compatibility_callback_info_type;
+using ::efl::eina::js::compatibility_return;
+using ::efl::eina::js::compatibility_get_pointer_internal_field;
+using ::efl::eina::js::compatibility_set_pointer_internal_field;
+
+void register_log_level_critical(v8::Isolate *isolate,
+                                 v8::Handle<v8::Object> global,
+                                 v8::Handle<v8::String> name);
+
+void register_log_level_err(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                            v8::Handle<v8::String> name);
+
+void register_log_level_warn(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name);
+
+void register_log_level_info(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name);
+
+void register_log_level_dbg(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                            v8::Handle<v8::String> name);
+
+void register_log_domain_global(v8::Isolate *isolate,
+                                v8::Handle<v8::Object> global,
+                                v8::Handle<v8::String> name);
+
+void register_log_print(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                        v8::Handle<v8::String> name);
+
+void register_log_domain_register(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name);
+
+void register_log_domain_unregister(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name);
+
+void register_log_domain_registered_level_get(v8::Isolate *isolate,
+                                              v8::Handle<v8::Object> global,
+                                              v8::Handle<v8::String> name);
+
+void register_log_domain_registered_level_set(v8::Isolate *isolate,
+                                              v8::Handle<v8::Object> global,
+                                              v8::Handle<v8::String> name);
+
+void register_log_print_cb_set(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name);
+
+void register_log_level_set(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                            v8::Handle<v8::String> name);
+
+void register_log_level_get(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                            v8::Handle<v8::String> name);
+
+void register_log_level_check(v8::Isolate *isolate,
+                              v8::Handle<v8::Object> global,
+                              v8::Handle<v8::String> name);
+
+void register_log_color_disable_set(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name);
+
+void register_log_color_disable_get(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name);
+
+void register_log_file_disable_set(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name);
+
+void register_log_file_disable_get(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name);
+
+void register_log_function_disable_set(v8::Isolate *isolate,
+                                       v8::Handle<v8::Object> global,
+                                       v8::Handle<v8::String> name);
+
+void register_log_function_disable_get(v8::Isolate *isolate,
+                                       v8::Handle<v8::Object> global,
+                                       v8::Handle<v8::String> name);
+
+void register_log_abort_on_critical_set(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name);
+
+void register_log_abort_on_critical_get(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name);
+
+void register_log_abort_on_critical_level_set(v8::Isolate *isolate,
+                                              v8::Handle<v8::Object> global,
+                                              v8::Handle<v8::String> name);
+
+void register_log_abort_on_critical_level_get(v8::Isolate *isolate,
+                                              v8::Handle<v8::Object> global,
+                                              v8::Handle<v8::String> name);
+
+void register_log_domain_level_set(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name);
+
+void register_log_domain_level_get(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name);
+
+void register_log_state_start(v8::Isolate *isolate,
+                              v8::Handle<v8::Object> global,
+                              v8::Handle<v8::String> name);
+
+void register_log_state_stop(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name);
+
+void register_log_timing(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                         v8::Handle<v8::String> name);
+
+} } } // namespace efl::js
+
+EAPI void eina_log_register(v8::Handle<v8::Object> exports, v8::Isolate* isolate);
+
+#endif /* EINA_JS_LOG_HH */
diff --git a/src/bindings/js/eina_js/eina_js_node.hh b/src/bindings/js/eina_js/eina_js_node.hh
new file mode 100644 (file)
index 0000000..cfa4169
--- /dev/null
@@ -0,0 +1,14 @@
+
+#ifdef HAVE_NODE_NODE_H
+#include <node/node.h>
+#elif defined(HAVE_NODEJS_DEPS_NODE_NODE_H)
+#include <nodejs/deps/node/node.h>
+#elif defined(HAVE_NODEJS_DEPS_NODE_INCLUDE_NODE_H)
+#include <nodejs/deps/node/include/node.h>
+#elif defined(HAVE_NODEJS_SRC_NODE_H)
+#include <nodejs/src/node.h>
+#elif defined(HAVE_NODE_H)
+#include <node.h>
+#else
+#error We must have at least one node header to include
+#endif
diff --git a/src/bindings/js/eina_js/eina_js_value.cc b/src/bindings/js/eina_js/eina_js_value.cc
new file mode 100644 (file)
index 0000000..5b5b822
--- /dev/null
@@ -0,0 +1,132 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eina_Js.hh>
+
+namespace efl { namespace eina { namespace js {
+
+namespace {
+
+compatibility_return_type eina_value_set(compatibility_callback_info_type args)
+{
+  if (args.Length() != 1)
+    return compatibility_return();
+
+  void *ptr = js::compatibility_get_pointer_internal_field(args.Holder(), 0);
+  v8::Isolate *isolate = args.GetIsolate();
+  try {
+    *static_cast<value*>(ptr) = value_cast<value>(args[0]);
+  } catch(const std::bad_cast &e) {
+    v8::Local<v8::Object> je = compatibility_new<v8::Object>(isolate);
+    je->Set(compatibility_new<v8::String>(isolate, "code"),
+            compatibility_new<v8::String>(isolate, "std::bad_cast"));
+    return compatibility_throw(isolate, je);
+  } catch(const ::efl::eina::system_error &e) {
+    v8::Local<v8::Object> je = compatibility_new<v8::Object>(isolate);
+    je->Set(compatibility_new<v8::String>(isolate, "code"),
+            compatibility_new<v8::String>(isolate, "std::error_code"));
+    je->Set(compatibility_new<v8::String>(isolate, "category"),
+            compatibility_new<v8::String>(isolate, e.code().category().name()));
+    je->Set(compatibility_new<v8::String>(isolate, "value"),
+            compatibility_new<v8::Integer>(isolate, e.code().value()));
+    return compatibility_throw(isolate, je);
+  }
+  return compatibility_return();
+}
+
+compatibility_return_type eina_value_get(compatibility_callback_info_type args)
+{
+  void *ptr = compatibility_get_pointer_internal_field(args.Holder(), 0);
+  auto &value = *static_cast<eina::value*>(ptr);
+  return compatibility_return
+    (value_cast<v8::Local<v8::Value>>(value, args.GetIsolate()), args);
+}
+
+compatibility_return_type eina_value_constructor(compatibility_callback_info_type args)
+{
+  if (args.Length() != 1)
+    return compatibility_return();
+
+  v8::Isolate* isolate = args.GetIsolate();
+
+  try {
+    std::unique_ptr<value>
+      ptr(new value(value_cast<value>(args[0])));
+    compatibility_set_pointer_internal_field(args.This(), 0, ptr.get());
+    ptr.release();
+  } catch(const std::bad_cast &e) {
+    v8::Local<v8::Object> je = compatibility_new<v8::Object>(isolate);
+    je->Set(compatibility_new<v8::String>(isolate, "code"),
+            compatibility_new<v8::String>(isolate, "std::bad_cast"));
+    return compatibility_throw(isolate,je);
+  } catch(const ::efl::eina::system_error &e) {
+    v8::Local<v8::Object> je = compatibility_new<v8::Object>(isolate);
+    je->Set(compatibility_new<v8::String>(isolate, "code"),
+            compatibility_new<v8::String>(isolate, "std::error_code"));
+    je->Set(compatibility_new<v8::String>(isolate, "category"),
+            compatibility_new<v8::String>(isolate, e.code().category().name()));
+    je->Set(compatibility_new<v8::String>(isolate, "value"),
+            compatibility_new<v8::Integer>(isolate, e.code().value()));
+    return compatibility_throw(isolate, je);
+  }
+  // makeweak
+  // {
+  //     typedef global_ref<v8::Object> persistent_t;
+  //     typedef v8::WeakCallbackData<v8::Object, persistent_t> cb_type;
+
+  //     auto on_gc = [](const cb_type &data) {
+  //         typedef ::efl::eina::value value_type;
+  //         typedef value_type *ptr_type;
+
+  //         auto o = data.GetValue();
+  //         delete static_cast<ptr_type>
+  //             (compatibility_get_pointer_internal_field(o, 0));
+  //         compatibility_set_pointer_internal_field<void*>(o, 0, nullptr);
+
+  //         delete data.GetParameter();
+  //     };
+
+  //     auto persistent = new persistent_t(isolate, args.This());
+  //     persistent->SetWeak<v8::Object>(persistent, on_gc);
+  // }
+}
+
+}
+      
+EAPI
+void register_value(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                         v8::Handle<v8::String> name)
+{
+  using v8::Isolate;
+  using v8::Local;
+  using v8::Value;
+  using v8::Integer;
+  using v8::String;
+  using v8::Object;
+  using v8::FunctionTemplate;
+  using v8::FunctionCallbackInfo;
+
+  v8::Local<v8::FunctionTemplate> constructor = compatibility_new<v8::FunctionTemplate>(isolate, &eina_value_constructor);
+  
+  v8::Local<v8::ObjectTemplate> instance = constructor->InstanceTemplate();
+  instance->SetInternalFieldCount(1);
+
+  auto prototype = constructor->PrototypeTemplate();
+  
+  prototype->Set(compatibility_new<v8::String>(isolate, "set")
+                 , compatibility_new<FunctionTemplate>(isolate, &eina_value_set));
+  prototype->Set(compatibility_new<v8::String>(isolate, "get")
+                 , compatibility_new<FunctionTemplate>(isolate, &eina_value_get));
+  
+  global->Set(name, constructor->GetFunction());
+}
+
+} } } // namespace efl { namespace js {
+
+EAPI
+void eina_value_register(v8::Handle<v8::Object> global, v8::Isolate* isolate)
+{
+  efl::eina::js::register_value(isolate, global
+                                , efl::eina::js::compatibility_new<v8::String>(isolate, "value"));
+}
diff --git a/src/bindings/js/eina_js/eina_js_value.hh b/src/bindings/js/eina_js/eina_js_value.hh
new file mode 100644 (file)
index 0000000..e6ebd30
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef EINA_JS_VALUE_HH
+#define EINA_JS_VALUE_HH
+
+#include <type_traits>
+
+#include <eina_js_compatibility.hh>
+
+namespace efl { namespace eina { namespace js {
+
+namespace detail {
+
+template<class T, class = void>
+struct is_representable_as_v8_integer: std::false_type {};
+
+template<class T>
+struct is_representable_as_v8_integer
+<T,
+ typename std::enable_if<std::is_integral<T>::value
+                         /* v8::Integer only stores 32-bit signed and unsigned
+                            numbers. */
+                         && (sizeof(T) <= sizeof(int32_t))>::type>
+: std::true_type {};
+
+template<class T>
+typename std::enable_if<is_representable_as_v8_integer<T>::value
+                        && std::is_signed<T>::value,
+                        v8::Local<v8::Value>>::type
+to_v8_number(const T &v, v8::Isolate *isolate)
+{
+  return compatibility_new<v8::Integer>(isolate, v);
+}
+
+template<class T>
+typename std::enable_if<is_representable_as_v8_integer<T>::value
+                        && std::is_unsigned<T>::value,
+                        v8::Local<v8::Value>>::type
+to_v8_number(const T &v, v8::Isolate *isolate)
+{
+  return compatibility_new<v8::Integer>(isolate, v);
+}
+
+template<class T>
+typename std::enable_if<(std::is_integral<T>::value
+                         && !is_representable_as_v8_integer<T>::value)
+                        || std::is_floating_point<T>::value,
+                        v8::Local<v8::Value>>::type
+to_v8_number(const T &v, v8::Isolate *isolate)
+{
+  return compatibility_new<v8::Number>(isolate, v);
+}
+
+template<class T>
+typename std::enable_if<std::is_same<T, ::efl::eina::stringshare>::value
+                        || std::is_same<T, std::string>::value,
+    v8::Local<v8::Value>>::type
+to_v8_string(const T &v, v8::Isolate *isolate)
+{
+  return compatibility_new<v8::String>(isolate, v.c_str());
+}
+
+} // namespace detail
+
+template<class T>
+typename std::enable_if<std::is_same<T, v8::Local<v8::Value>>::value, T>::type
+value_cast(const ::efl::eina::value &v, v8::Isolate *isolate)
+{
+    using detail::to_v8_number;
+    using detail::to_v8_string;
+    using ::efl::eina::get;
+
+    const auto &t = v.type_info();
+    if (t == EINA_VALUE_TYPE_UINT64) {
+        return to_v8_number(get<uint64_t>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_UCHAR) {
+        return to_v8_number(get<unsigned char>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_USHORT) {
+        return to_v8_number(get<unsigned short>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_UINT) {
+        return to_v8_number(get<unsigned int>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_ULONG) {
+        return to_v8_number(get<unsigned long>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_CHAR) {
+        return to_v8_number(get<char>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_SHORT) {
+        return to_v8_number(get<short>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_INT) {
+        return to_v8_number(get<int>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_LONG) {
+        return to_v8_number(get<long>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_FLOAT) {
+        return to_v8_number(get<float>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_DOUBLE) {
+        return to_v8_number(get<double>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_STRINGSHARE) {
+        return to_v8_string(get<::efl::eina::stringshare>(v), isolate);
+    } else if (t == EINA_VALUE_TYPE_STRING) {
+        return to_v8_string(get<std::string>(v), isolate);
+    }
+
+    throw std::bad_cast{};
+}
+
+template<class T>
+typename std::enable_if<std::is_same<T, ::efl::eina::value>::value, T>::type
+value_cast(const v8::Handle<v8::Value> &v)
+{
+    using ::efl::eina::value;
+
+    if (v->IsBoolean()) {
+        return value(int{v->BooleanValue()});
+    } else if (v->IsInt32()) {
+        return value(v->Int32Value());
+    } else if (v->IsUint32()) {
+        return value(v->Uint32Value());
+    } else if (v->IsNumber()) {
+        return value(v->NumberValue());
+    } else if (v->IsString()) {
+        v8::String::Utf8Value data(v);
+        return value(std::string(*data, data.length()));
+    }
+
+    throw std::bad_cast{};
+}
+
+/*
+  # JS binding
+
+  - There is the `value()` constructor, which accepts a primitive value as input
+    argument and might throw.
+    - The returned object has a `get()` method, which can be used to get the
+      wrapped value as a JavaScript value.
+    - The returned object has a `set()` method, which can be used to change the
+      wrapped value.
+ */
+void register_value(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                    v8::Handle<v8::String> name);
+
+} } } // namespace efl::js
+
+EAPI void eina_value_register(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+
+#endif /* EINA_JS_VALUE_HH */
diff --git a/src/bindings/js/eio_js/Eio_Js.hh b/src/bindings/js/eio_js/Eio_Js.hh
new file mode 100644 (file)
index 0000000..e379229
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef EIO_JS_INIT_HH
+#define EIO_JS_INIT_HH
+
+#include <Eio.h>
+#include <Ecore.h>
+
+#include <Eina.hh>
+
+#include <Eina_Js.hh>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_EIO_JS_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_EIO_JS_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+namespace efl { namespace eio { namespace js {
+
+EAPI
+void register_eio(v8::Isolate* isolate, v8::Handle<v8::Object> exports);      
+
+} } } // namespace efl { namespace eio { namespace js {
+
+#endif /* EIO_JS_INIT_HH */
diff --git a/src/bindings/js/eio_js/eio_js.cc b/src/bindings/js/eio_js/eio_js.cc
new file mode 100644 (file)
index 0000000..8441247
--- /dev/null
@@ -0,0 +1,1756 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eio_Js.hh>
+
+namespace efl { namespace eio { namespace js {
+
+using ::efl::eina::js::compatibility_new;
+using ::efl::eina::js::compatibility_return_type;
+using ::efl::eina::js::compatibility_callback_info_type;
+using ::efl::eina::js::compatibility_return;
+using ::efl::eina::js::compatibility_get_pointer_internal_field;
+using ::efl::eina::js::compatibility_set_pointer_internal_field;
+
+namespace {
+      
+Eio_File* extract_eio_file(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field<Eio_File*>(object, 0);
+}
+
+v8::Local<v8::Object> wrap_eio_file(Eio_File *file, v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::Boolean;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto cancel = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+
+        auto ret = eio_file_cancel(extract_eio_file(info.This()));
+        return compatibility_return(compatibility_new<Boolean>(isolate, ret),
+                                    info);
+    };
+
+    auto check = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+
+        auto ret = eio_file_check(extract_eio_file(info.This()));
+        return compatibility_return(compatibility_new<Boolean>(isolate, ret),
+                                    info);
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "cancel"),
+             compatibility_new<FunctionTemplate>(isolate, cancel)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "check"),
+             compatibility_new<FunctionTemplate>(isolate, check)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, file);
+
+    return ret;
+}
+
+static Eina_File* extract_eina_file(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field<Eina_File*>(object, 0);
+}
+
+static v8::Local<v8::Object> wrap_eina_file(Eina_File *file,
+                                            v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::Object;
+    using v8::FunctionTemplate;
+    using v8::WeakCallbackData;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    /* TODO:
+
+       Eina_File only handle files open in read-only mode. Althought there
+       aren't many useful functions exposed to a JavaScript binding, the exposed
+       `file->fd` can be used to expose a few read operations found in
+       `<cstdio>`.
+       */
+
+    auto close = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto o = info.This();
+
+        auto file = extract_eina_file(o);
+        if (!file)
+            return compatibility_return();
+
+        eina_file_close(file);
+        compatibility_set_pointer_internal_field<void*>(o, 0, nullptr);
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "close"),
+             compatibility_new<FunctionTemplate>(isolate, close)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, file);
+
+    auto on_gc = [ret]() {
+      auto file = extract_eina_file(ret);
+
+      if (file) {
+        eina_file_close(file);
+        compatibility_set_pointer_internal_field<void*>(ret, 0, nullptr);
+      }
+    };
+    
+    efl::eina::js::make_weak(isolate, ret, on_gc);
+
+    return ret;
+}
+
+static Eio_Monitor* extract_monitor(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field<Eio_Monitor*>(object, 0);
+}
+
+static v8::Local<v8::Object> wrap_monitor(Eio_Monitor *monitor,
+                                          v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        eio_monitor_del(extract_monitor(info.This()));
+        return compatibility_return();
+    };
+
+    auto path_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto ret = eio_monitor_path_get(extract_monitor(info.This()));
+        return compatibility_return(compatibility_new<String>(info.GetIsolate(),
+                                                              ret),
+                                    info);
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "path_get"),
+             compatibility_new<FunctionTemplate>(isolate, path_get)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, monitor);
+
+    return ret;
+}
+
+static Ecore_Event_Handler *extract_event_handler(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field<Ecore_Event_Handler*>
+        (object, 0);
+}
+
+static v8::Local<v8::Object> wrap_event_handler(Ecore_Event_Handler *handler,
+                                                v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+    using v8::Value;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto p = ecore_event_handler_del(extract_event_handler(info.This()));
+
+        auto per = static_cast<efl::eina::js::global_ref<Value>*>(p);
+        per->dispose();
+        delete per;
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, handler);
+
+    return ret;
+}
+
+static
+v8::Local<v8::Object> wrap_eina_file_direct_info(const Eina_File_Direct_Info*
+                                                 info,
+                                                 v8::Isolate *isolate)
+{
+    using v8::Object;
+    using v8::String;
+    using v8::Integer;
+
+    auto wrapped_info = compatibility_new<Object>(isolate);
+
+    wrapped_info->Set(compatibility_new<String>(isolate, "path_length"),
+                      compatibility_new<Integer>(isolate, info->path_length));
+    wrapped_info->Set(compatibility_new<String>(isolate, "mame_length"),
+                      compatibility_new<Integer>(isolate, info->name_length));
+    wrapped_info->Set(compatibility_new<String>(isolate, "name_start"),
+                      compatibility_new<Integer>(isolate, info->name_start));
+    wrapped_info->Set(compatibility_new<String>(isolate, "type"),
+                      compatibility_new<Integer>(isolate, info->type));
+    wrapped_info->Set(compatibility_new<String>(isolate, "path"),
+                      compatibility_new<String>(isolate, info->path));
+
+    return wrapped_info;
+}
+
+EAPI
+void register_init(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                   v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto init = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = eio_init();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, init)
+                ->GetFunction());
+}
+
+EAPI
+void register_shutdown(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                       v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto shutdown = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = eio_shutdown();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, shutdown)
+                ->GetFunction());
+}
+
+EAPI
+void register_op_file_copy(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                           v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name, compatibility_new<Integer>(isolate, EIO_FILE_COPY));
+}
+
+EAPI
+void register_op_file_move(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                           v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name, compatibility_new<Integer>(isolate, EIO_FILE_MOVE));
+}
+
+EAPI
+void register_op_dir_copy(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                          v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name, compatibility_new<Integer>(isolate, EIO_DIR_COPY));
+}
+
+EAPI
+void register_op_dir_move(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                          v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name, compatibility_new<Integer>(isolate, EIO_DIR_MOVE));
+}
+
+EAPI
+void register_op_unlink(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                        v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name, compatibility_new<Integer>(isolate, EIO_UNLINK));
+}
+
+EAPI
+void register_op_file_getpwnam(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name, compatibility_new<Integer>(isolate, EIO_FILE_GETPWNAM));
+}
+
+EAPI
+void register_op_file_getgrnam(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name, compatibility_new<Integer>(isolate, EIO_FILE_GETGRNAM));
+}
+
+EAPI
+void register_file_open(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                        v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::Value;
+    using v8::String;
+    using v8::FunctionTemplate;
+    using v8::Function;
+    using v8::Handle;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 4 || !args[0]->IsString() || !args[1]->IsBoolean()
+            || !args[2]->IsFunction() || !args[3]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[2]);
+        cb_data[0] = persistent_t(isolate, args[2]);
+        cb_data[1] = persistent_t(isolate, args[3]);
+
+        auto open_cb = [](void *data, Eio_File *handler, Eina_File *file) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                wrap_eina_file(file, isolate)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] persistent;
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 1);
+        };
+
+        auto ret = eio_file_open(*String::Utf8Value(args[0]),
+                                 args[1]->BooleanValue(), open_cb, error_cb,
+                                 cb_data.release());
+
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_monitor_file_created(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, EIO_MONITOR_FILE_CREATED));
+}
+
+EAPI
+void register_monitor_file_deleted(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, EIO_MONITOR_FILE_DELETED));
+}
+
+EAPI
+void register_monitor_file_modified(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, EIO_MONITOR_FILE_MODIFIED));
+}
+
+EAPI
+void register_monitor_file_closed(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, EIO_MONITOR_FILE_CLOSED));
+}
+
+EAPI
+void register_monitor_directory_created(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           EIO_MONITOR_DIRECTORY_CREATED));
+}
+
+EAPI
+void register_monitor_directory_deleted(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           EIO_MONITOR_DIRECTORY_DELETED));
+}
+
+EAPI
+void register_monitor_directory_modified(v8::Isolate *isolate,
+                                         v8::Handle<v8::Object> global,
+                                         v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           EIO_MONITOR_DIRECTORY_MODIFIED));
+}
+
+EAPI
+void register_monitor_directory_closed(v8::Isolate *isolate,
+                                       v8::Handle<v8::Object> global,
+                                       v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           EIO_MONITOR_DIRECTORY_CLOSED));
+}
+
+EAPI
+void register_monitor_self_rename(v8::Isolate *isolate,
+                                  v8::Handle<v8::Object> global,
+                                  v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, EIO_MONITOR_SELF_RENAME));
+}
+
+EAPI
+void register_monitor_self_deleted(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, EIO_MONITOR_SELF_DELETED));
+}
+
+EAPI
+void register_monitor_error(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                            v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, EIO_MONITOR_ERROR));
+}
+
+EAPI
+void register_monitor_add(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                          v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsString())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = eio_monitor_add(*String::Utf8Value(args[0]));
+        return compatibility_return(wrap_monitor(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+template<int &wanted_event>
+static
+void register_monitor_event_handler_add(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::String;
+    using v8::Value;
+    using v8::Object;
+    using v8::Function;
+    using v8::Handle;
+    using v8::Local;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+
+        auto p = new efl::eina::js::global_ref<Value>(isolate, args[0]);
+
+        auto cb = [](void *d, int type, void *event) -> Eina_Bool {
+            auto p = reinterpret_cast<efl::eina::js::global_ref<Value>*>(d);
+            auto e = reinterpret_cast<Eio_Monitor_Event*>(event);
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+           auto o = p->handle();
+            auto wrapped_event = compatibility_new<Object>(isolate);
+
+            wrapped_event->Set(compatibility_new<String>(isolate, "monitor"),
+                               wrap_monitor(e->monitor, isolate));
+            wrapped_event->Set(compatibility_new<String>(isolate, "filename"),
+                               compatibility_new<String>(isolate, e->filename));
+
+            Handle<Value> args[2]{
+                compatibility_new<Integer>(isolate, type),
+                wrapped_event
+            };
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 2, args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+
+        auto ret = ecore_event_handler_add(wanted_event, cb, p);
+        return compatibility_return(wrap_event_handler(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void
+register_event_monitor_file_created_handler_add(v8::Isolate *isolate,
+                                                v8::Handle<v8::Object> global,
+                                                v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_FILE_CREATED>
+        (isolate, global, name);
+}
+
+EAPI
+void
+register_event_monitor_file_deleted_handler_add(v8::Isolate *isolate,
+                                                v8::Handle<v8::Object> global,
+                                                v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_FILE_DELETED>
+        (isolate, global, name);
+}
+
+EAPI
+void
+register_event_monitor_file_modified_handler_add(v8::Isolate *isolate,
+                                                 v8::Handle<v8::Object> global,
+                                                 v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_FILE_MODIFIED>
+        (isolate, global, name);
+}
+
+EAPI
+void
+register_event_monitor_file_closed_handler_add(v8::Isolate *isolate,
+                                               v8::Handle<v8::Object> global,
+                                               v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_FILE_CLOSED>
+        (isolate, global, name);
+}
+
+EAPI
+void register_event_monitor_directory_created_handler_add
+(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+ v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_DIRECTORY_CREATED>
+        (isolate, global, name);
+}
+
+EAPI
+void register_event_monitor_directory_deleted_handler_add
+(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+ v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_DIRECTORY_DELETED>
+        (isolate, global, name);
+}
+
+EAPI
+void register_event_monitor_directory_modified_handler_add
+(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+ v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_DIRECTORY_MODIFIED>
+        (isolate, global, name);
+}
+
+EAPI
+void register_event_monitor_directory_closed_handler_add
+(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+ v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_DIRECTORY_CLOSED>
+        (isolate, global, name);
+}
+
+EAPI
+void
+register_event_monitor_self_rename_handler_add(v8::Isolate *isolate,
+                                               v8::Handle<v8::Object> global,
+                                               v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_SELF_RENAME>
+        (isolate, global, name);
+}
+
+EAPI
+void
+register_event_monitor_self_deleted_handler_add(v8::Isolate *isolate,
+                                                v8::Handle<v8::Object> global,
+                                                v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_SELF_DELETED>
+        (isolate, global, name);
+}
+
+EAPI
+void
+register_event_monitor_error_handler_add(v8::Isolate *isolate,
+                                         v8::Handle<v8::Object> global,
+                                         v8::Handle<v8::String> name)
+{
+    return register_monitor_event_handler_add<EIO_MONITOR_ERROR>
+        (isolate, global, name);
+}
+
+EAPI
+void register_file_ls(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                      v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 5 || !args[0]->IsString() || !args[1]->IsFunction()
+            || !args[2]->IsFunction() || !args[3]->IsFunction()
+            || !args[4]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[4]);
+        cb_data[0] = persistent_t(isolate, args[1]);
+        cb_data[1] = persistent_t(isolate, args[2]);
+        cb_data[2] = persistent_t(isolate, args[3]);
+        cb_data[3] = persistent_t(isolate, args[4]);
+
+        auto filter_cb = [](void *data, Eio_File *handler, const char *file)
+            -> Eina_Bool {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<String>(isolate, file)
+            };
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 2, args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+        auto main_cb = [](void *data, Eio_File *handler, const char *file) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<String>(isolate, file)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+        };
+        auto done_cb = [](void *data, Eio_File *handler) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 2;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = wrap_eio_file(handler, isolate);
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete[] (persistent - 2);
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 3;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 3);
+        };
+
+        auto ret = eio_file_ls(*String::Utf8Value(args[0]), filter_cb, main_cb,
+                               done_cb, error_cb, cb_data.release());
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_file_chmod(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                         v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 4 || !args[0]->IsString() || !args[1]->IsNumber()
+            || !args[2]->IsFunction() || !args[3]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[2]);
+        cb_data[0] = persistent_t(isolate, args[2]);
+        cb_data[1] = persistent_t(isolate, args[3]);
+        auto done_cb = [](void *data, Eio_File *handler) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = wrap_eio_file(handler, isolate);
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete[] persistent;
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 1);
+        };
+
+        auto ret = eio_file_chmod(*String::Utf8Value(args[0]),
+                                  args[1]->IntegerValue(), done_cb, error_cb,
+                                  cb_data.release());
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_file_chown(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                         v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 5 || !args[0]->IsString() || !args[1]->IsString()
+            || !args[2]->IsString() || !args[3]->IsFunction()
+            || !args[4]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[2]);
+        cb_data[0] = persistent_t(isolate, args[3]);
+        cb_data[1] = persistent_t(isolate, args[4]);
+        auto done_cb = [](void *data, Eio_File *handler) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = wrap_eio_file(handler, isolate);
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete[] persistent;
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 1);
+        };
+
+        auto ret = eio_file_chown(*String::Utf8Value(args[0]),
+                                  *String::Utf8Value(args[1]),
+                                  *String::Utf8Value(args[2]), done_cb,
+                                  error_cb,
+                                  cb_data.release());
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_file_unlink(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                          v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 3 || !args[0]->IsString() || !args[1]->IsFunction()
+            || !args[2]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[2]);
+        cb_data[0] = persistent_t(isolate, args[1]);
+        cb_data[1] = persistent_t(isolate, args[2]);
+        auto done_cb = [](void *data, Eio_File *handler) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = wrap_eio_file(handler, isolate);
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete[] persistent;
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 1);
+        };
+
+        auto ret = eio_file_unlink(*String::Utf8Value(args[0]), done_cb,
+                                   error_cb, cb_data.release());
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_file_mkdir(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                         v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 4 || !args[0]->IsString() || !args[1]->IsNumber()
+            || !args[2]->IsString() || !args[3]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[2]);
+        cb_data[0] = persistent_t(isolate, args[2]);
+        cb_data[1] = persistent_t(isolate, args[3]);
+        auto done_cb = [](void *data, Eio_File *handler) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = wrap_eio_file(handler, isolate);
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete[] persistent;
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 1);
+        };
+
+        auto ret = eio_file_mkdir(*String::Utf8Value(args[0]),
+                                  args[1]->IntegerValue(), done_cb, error_cb,
+                                  cb_data.release());
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_file_move(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                        v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::Number;
+    using v8::Object;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 5 || !args[0]->IsString() || !args[1]->IsString()
+            || !args[2]->IsFunction() || !args[3]->IsFunction()
+            || !args[4]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[3]);
+        cb_data[0] = persistent_t(isolate, args[2]);
+        cb_data[1] = persistent_t(isolate, args[3]);
+        cb_data[2] = persistent_t(isolate, args[4]);
+        auto progress_cb = [](void *data, Eio_File *handler,
+                              const Eio_Progress *info) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            auto wrapped_info = compatibility_new<Object>(isolate);
+
+            wrapped_info->Set(compatibility_new<String>(isolate, "op"),
+                              compatibility_new<Integer>(isolate, info->op));
+            wrapped_info->Set(compatibility_new<String>(isolate, "current"),
+                              compatibility_new<Integer>(isolate,
+                                                         info->current));
+            wrapped_info->Set(compatibility_new<String>(isolate, "max"),
+                              compatibility_new<Integer>(isolate, info->max));
+            wrapped_info->Set(compatibility_new<String>(isolate, "percent"),
+                              compatibility_new<Number>(isolate,
+                                                        info->percent));
+            wrapped_info->Set(compatibility_new<String>(isolate, "source"),
+                              compatibility_new<String>(isolate, info->source));
+            wrapped_info->Set(compatibility_new<String>(isolate, "dest"),
+                              compatibility_new<String>(isolate, info->dest));
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                wrapped_info
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+        };
+        auto done_cb = [](void *data, Eio_File *handler) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = wrap_eio_file(handler, isolate);
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete[] (persistent - 1);
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 2;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 2);
+        };
+
+        auto ret = eio_file_move(*String::Utf8Value(args[0]),
+                                 *String::Utf8Value(args[1]),
+                                 progress_cb, done_cb, error_cb,
+                                 cb_data.release());
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_file_copy(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                        v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::Number;
+    using v8::Object;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 5 || !args[0]->IsString() || !args[1]->IsString()
+            || !args[2]->IsFunction() || !args[3]->IsFunction()
+            || !args[4]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[3]);
+        cb_data[0] = persistent_t(isolate, args[2]);
+        cb_data[1] = persistent_t(isolate, args[3]);
+        cb_data[2] = persistent_t(isolate, args[4]);
+        auto progress_cb = [](void *data, Eio_File *handler,
+                              const Eio_Progress *info) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            auto wrapped_info = compatibility_new<Object>(isolate);
+
+            wrapped_info->Set(compatibility_new<String>(isolate, "op"),
+                              compatibility_new<Integer>(isolate, info->op));
+            wrapped_info->Set(compatibility_new<String>(isolate, "current"),
+                              compatibility_new<Integer>(isolate,
+                                                         info->current));
+            wrapped_info->Set(compatibility_new<String>(isolate, "max"),
+                              compatibility_new<Integer>(isolate, info->max));
+            wrapped_info->Set(compatibility_new<String>(isolate, "percent"),
+                              compatibility_new<Number>(isolate,
+                                                        info->percent));
+            wrapped_info->Set(compatibility_new<String>(isolate, "source"),
+                              compatibility_new<String>(isolate, info->source));
+            wrapped_info->Set(compatibility_new<String>(isolate, "dest"),
+                              compatibility_new<String>(isolate, info->dest));
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                wrapped_info
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+        };
+        auto done_cb = [](void *data, Eio_File *handler) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = wrap_eio_file(handler, isolate);
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete[] (persistent - 1);
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 2;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 2);
+        };
+
+        auto ret = eio_file_copy(*String::Utf8Value(args[0]),
+                                 *String::Utf8Value(args[1]),
+                                 progress_cb, done_cb, error_cb,
+                                 cb_data.release());
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_dir_move(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                       v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::Number;
+    using v8::Object;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 6 || !args[0]->IsString() || !args[1]->IsString()
+            || !args[2]->IsFunction() || !args[3]->IsFunction()
+            || !args[4]->IsFunction() || !args[5]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[4]);
+        cb_data[0] = persistent_t(isolate, args[2]);
+        cb_data[1] = persistent_t(isolate, args[3]);
+        cb_data[2] = persistent_t(isolate, args[4]);
+        cb_data[3] = persistent_t(isolate, args[5]);
+        auto filter_cb = [](void *data, Eio_File *handler,
+                            const Eina_File_Direct_Info *info) -> Eina_Bool {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                wrap_eina_file_direct_info(info, isolate)
+            };
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 2, args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+        auto progress_cb = [](void *data, Eio_File *handler,
+                              const Eio_Progress *info) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            auto wrapped_info = compatibility_new<Object>(isolate);
+
+            wrapped_info->Set(compatibility_new<String>(isolate, "op"),
+                              compatibility_new<Integer>(isolate, info->op));
+            wrapped_info->Set(compatibility_new<String>(isolate, "current"),
+                              compatibility_new<Integer>(isolate,
+                                                         info->current));
+            wrapped_info->Set(compatibility_new<String>(isolate, "max"),
+                              compatibility_new<Integer>(isolate, info->max));
+            wrapped_info->Set(compatibility_new<String>(isolate, "percent"),
+                              compatibility_new<Number>(isolate,
+                                                        info->percent));
+            wrapped_info->Set(compatibility_new<String>(isolate, "source"),
+                              compatibility_new<String>(isolate, info->source));
+            wrapped_info->Set(compatibility_new<String>(isolate, "dest"),
+                              compatibility_new<String>(isolate, info->dest));
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                wrapped_info
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+        };
+        auto done_cb = [](void *data, Eio_File *handler) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 2;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = wrap_eio_file(handler, isolate);
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete[] (persistent - 2);
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 3;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 3);
+        };
+
+        auto ret = eio_dir_move(*String::Utf8Value(args[0]),
+                                *String::Utf8Value(args[1]), filter_cb,
+                                progress_cb, done_cb, error_cb,
+                                cb_data.release());
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_dir_copy(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                       v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::Number;
+    using v8::Object;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 6 || !args[0]->IsString() || !args[1]->IsString()
+            || !args[2]->IsFunction() || !args[3]->IsFunction()
+            || !args[4]->IsFunction() || !args[5]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[4]);
+        cb_data[0] = persistent_t(isolate, args[2]);
+        cb_data[1] = persistent_t(isolate, args[3]);
+        cb_data[2] = persistent_t(isolate, args[4]);
+        cb_data[3] = persistent_t(isolate, args[5]);
+        auto filter_cb = [](void *data, Eio_File *handler,
+                            const Eina_File_Direct_Info *info) -> Eina_Bool {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                wrap_eina_file_direct_info(info, isolate)
+            };
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 2, args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+        auto progress_cb = [](void *data, Eio_File *handler,
+                              const Eio_Progress *info) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            auto wrapped_info = compatibility_new<Object>(isolate);
+
+            wrapped_info->Set(compatibility_new<String>(isolate, "op"),
+                              compatibility_new<Integer>(isolate, info->op));
+            wrapped_info->Set(compatibility_new<String>(isolate, "current"),
+                              compatibility_new<Integer>(isolate,
+                                                         info->current));
+            wrapped_info->Set(compatibility_new<String>(isolate, "max"),
+                              compatibility_new<Integer>(isolate, info->max));
+            wrapped_info->Set(compatibility_new<String>(isolate, "percent"),
+                              compatibility_new<Number>(isolate,
+                                                        info->percent));
+            wrapped_info->Set(compatibility_new<String>(isolate, "source"),
+                              compatibility_new<String>(isolate, info->source));
+            wrapped_info->Set(compatibility_new<String>(isolate, "dest"),
+                              compatibility_new<String>(isolate, info->dest));
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                wrapped_info
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+        };
+        auto done_cb = [](void *data, Eio_File *handler) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 2;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = wrap_eio_file(handler, isolate);
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete[] (persistent - 2);
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 3;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 3);
+        };
+
+        auto ret = eio_dir_copy(*String::Utf8Value(args[0]),
+                                *String::Utf8Value(args[1]), filter_cb,
+                                progress_cb, done_cb, error_cb,
+                                cb_data.release());
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+EAPI
+void register_dir_unlink(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                         v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::Number;
+    using v8::Object;
+    using v8::FunctionTemplate;
+    using v8::Handle;
+    using v8::Value;
+    using v8::Function;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 5 || !args[0]->IsString() || !args[1]->IsFunction()
+            || !args[2]->IsFunction() || !args[3]->IsFunction()
+            || !args[4]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+
+        auto cb_data = unique_ptr<persistent_t[]>(new persistent_t[4]);
+        cb_data[0] = persistent_t(isolate, args[1]);
+        cb_data[1] = persistent_t(isolate, args[2]);
+        cb_data[2] = persistent_t(isolate, args[3]);
+        cb_data[3] = persistent_t(isolate, args[4]);
+        auto filter_cb = [](void *data, Eio_File *handler,
+                            const Eina_File_Direct_Info *info) -> Eina_Bool {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                wrap_eina_file_direct_info(info, isolate)
+            };
+
+            auto ret = Function::Cast(*o)->Call(o->ToObject(), 2, args);
+            auto bret = ret->IsBoolean() && ret->BooleanValue();
+            return bret ? EINA_TRUE : EINA_FALSE;
+        };
+        auto progress_cb = [](void *data, Eio_File *handler,
+                              const Eio_Progress *info) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 1;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            auto wrapped_info = compatibility_new<Object>(isolate);
+
+            wrapped_info->Set(compatibility_new<String>(isolate, "op"),
+                              compatibility_new<Integer>(isolate, info->op));
+            wrapped_info->Set(compatibility_new<String>(isolate, "current"),
+                              compatibility_new<Integer>(isolate,
+                                                         info->current));
+            wrapped_info->Set(compatibility_new<String>(isolate, "max"),
+                              compatibility_new<Integer>(isolate, info->max));
+            wrapped_info->Set(compatibility_new<String>(isolate, "percent"),
+                              compatibility_new<Number>(isolate,
+                                                        info->percent));
+            wrapped_info->Set(compatibility_new<String>(isolate, "source"),
+                              compatibility_new<String>(isolate, info->source));
+            wrapped_info->Set(compatibility_new<String>(isolate, "dest"),
+                              compatibility_new<String>(isolate, info->dest));
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                wrapped_info
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+        };
+        auto done_cb = [](void *data, Eio_File *handler) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 2;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args = wrap_eio_file(handler, isolate);
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete[] (persistent - 2);
+        };
+        auto error_cb = [](void *data, Eio_File *handler, int error) {
+            auto persistent = reinterpret_cast<persistent_t*>(data) + 3;
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_eio_file(handler, isolate),
+                compatibility_new<Integer>(isolate, error)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete[] (persistent - 3);
+        };
+
+        auto ret = eio_dir_unlink(*String::Utf8Value(args[0]), filter_cb,
+                                  progress_cb, done_cb, error_cb,
+                                  cb_data.release());
+        return compatibility_return(wrap_eio_file(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+}
+
+EAPI
+void register_eio(v8::Isolate* isolate, v8::Handle<v8::Object> exports)
+{
+   using v8::String;
+   register_init(isolate, exports,
+                 compatibility_new<String>(isolate, "eio_init"));
+   register_shutdown(isolate, exports,
+                     compatibility_new<String>(isolate, "eio_shutdown"));
+   register_op_file_copy(isolate, exports,
+                         compatibility_new<String>(isolate, "EIO_FILE_COPY"));
+   register_op_file_move(isolate, exports,
+                         compatibility_new<String>(isolate, "EIO_FILE_MOVE"));
+   register_op_dir_copy(isolate, exports,
+                        compatibility_new<String>(isolate, "EIO_DIR_COPY"));
+   register_op_dir_move(isolate, exports,
+                        compatibility_new<String>(isolate, "EIO_DIR_MOVE"));
+   register_op_unlink(isolate, exports,
+                      compatibility_new<String>(isolate, "EIO_LINK"));
+   register_op_file_getpwnam(isolate, exports,
+                             compatibility_new<String>(isolate,
+                                                       "EIO_FILE_GETPWNAM"));
+   register_op_file_getgrnam(isolate, exports,
+                             compatibility_new<String>(isolate,
+                                                       "EIO_FILE_GETGRNAM"));
+   register_file_open(isolate, exports,
+                      compatibility_new<String>(isolate, "eio_file_open"));
+   register_monitor_file_created(isolate, exports,
+                                 compatibility_new<String>(isolate,
+                                                           "EIO_MONITOR_FILE"
+                                                           "_CREATED"));
+   register_monitor_file_deleted(isolate, exports,
+                                 compatibility_new<String>(isolate,
+                                                           "EIO_MONITOR_FILE"
+                                                           "_DELETED"));
+   register_monitor_file_modified(isolate, exports,
+                                  compatibility_new<String>(isolate,
+                                                            "EIO_MONITOR_FILE"
+                                                            "_MODIFIED"));
+   register_monitor_file_closed(isolate, exports,
+                                compatibility_new<String>(isolate,
+                                                          "EIO_MONITOR_FILE"
+                                                          "_CLOSED"));
+   register_monitor_directory_created(isolate, exports,
+                                      compatibility_new<String>
+                                      (isolate,
+                                       "EIO_MONITOR_DIRECTORY_CREATED"));
+   register_monitor_directory_deleted(isolate, exports,
+                                      compatibility_new<String>
+                                      (isolate,
+                                       "EIO_MONITOR_DIRECTORY_DELETED"));
+   register_monitor_directory_modified(isolate, exports,
+                                       compatibility_new<String>
+                                       (isolate,
+                                        "EIO_MONITOR_DIRECTORY_MODIFIED"));
+   register_monitor_directory_closed(isolate, exports,
+                                     compatibility_new<String>
+                                     (isolate, "EIO_MONITOR_DIRECTORY_CLOSED"));
+   register_monitor_self_rename(isolate, exports,
+                                compatibility_new<String>
+                                (isolate, "EIO_MONITOR_SELF_RENAME"));
+   register_monitor_self_deleted(isolate, exports,
+                                 compatibility_new<String>
+                                 (isolate, "EIO_MONITOR_SELF_DELETED"));
+   register_monitor_error(isolate, exports,
+                          compatibility_new<String>(isolate,
+                                                    "EIO_MONITOR_ERROR"));
+   register_monitor_add(isolate, exports,
+                        compatibility_new<String>(isolate, "eio_monitor_add"));
+   register_event_monitor_file_created_handler_add
+     (isolate, exports,
+      compatibility_new<String>(isolate,
+                                "eio_event_monitor_file_created_handler_add"));
+   register_event_monitor_file_deleted_handler_add
+     (isolate, exports,
+      compatibility_new<String>(isolate,
+                                "eio_event_monitor_file_deleted_handler_add"));
+   register_event_monitor_file_modified_handler_add
+     (isolate, exports,
+      compatibility_new<String>
+      (isolate, "eio_event_monitor_file_modified_handler_add"));
+   register_event_monitor_file_closed_handler_add
+     (isolate, exports,
+      compatibility_new<String>(isolate,
+                                "eio_event_monitor_file_closed_handler_add"));
+   register_event_monitor_directory_created_handler_add
+     (isolate, exports,
+      compatibility_new<String>
+      (isolate, "eio_event_monitor_directory_created_handler_add"));
+   register_event_monitor_directory_deleted_handler_add
+     (isolate, exports,
+      compatibility_new<String>
+      (isolate, "eio_event_monitor_directory_deleted_handler_add"));
+   register_event_monitor_directory_modified_handler_add
+     (isolate, exports,
+      compatibility_new<String>
+      (isolate, "eio_event_monitor_directory_modified_handler_add"));
+   register_event_monitor_directory_closed_handler_add
+     (isolate, exports,
+      compatibility_new<String>
+      (isolate, "eio_event_monitor_directory_closed_handler_add"));
+   register_event_monitor_self_rename_handler_add
+     (isolate, exports,
+      compatibility_new<String>(isolate,
+                                "eio_event_monitor_self_rename_handler_add"));
+   register_event_monitor_self_deleted_handler_add
+     (isolate, exports,
+      compatibility_new<String>(isolate,
+                                "eio_event_monitor_self_deleted_handler_add"));
+   register_event_monitor_error_handler_add
+     (isolate, exports,
+      compatibility_new<String>(isolate,
+                                "eio_event_monitor_error_handler_add"));
+   register_file_ls(isolate, exports,
+                    compatibility_new<String>(isolate, "eio_file_ls"));
+   register_file_chmod(isolate, exports,
+                       compatibility_new<String>(isolate, "eio_file_chmod"));
+   register_file_chown(isolate, exports,
+                       compatibility_new<String>(isolate, "eio_file_chown"));
+   register_file_unlink(isolate, exports,
+                        compatibility_new<String>(isolate, "eio_file_unlink"));
+   register_file_mkdir(isolate, exports,
+                       compatibility_new<String>(isolate, "eio_file_mkdir"));
+   register_file_move(isolate, exports,
+                      compatibility_new<String>(isolate, "eio_file_move"));
+   register_file_copy(isolate, exports,
+                      compatibility_new<String>(isolate, "eio_file_copy"));
+   register_dir_move(isolate, exports,
+                     compatibility_new<String>(isolate, "eio_dir_move"));
+   register_dir_copy(isolate, exports,
+                     compatibility_new<String>(isolate, "eio_dir_copy"));
+   register_dir_unlink(isolate, exports,
+                       compatibility_new<String>(isolate, "eio_dir_unlink"));
+}
+      
+} } } // namespace efl { namespace eio { namespace js {
diff --git a/src/bindings/js/eldbus_js/Eldbus_Js.hh b/src/bindings/js/eldbus_js/Eldbus_Js.hh
new file mode 100644 (file)
index 0000000..00da9ca
--- /dev/null
@@ -0,0 +1,48 @@
+
+#ifndef EFL_ELDBUS_JS_HH
+#define EFL_ELDBUS_JS_HH
+
+#include <Eina.hh>
+#include <Eina_Js.hh>
+
+#include <Eldbus.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_EINA_JS_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+namespace efl { namespace eldbus { namespace js {
+
+EAPI void register_eldbus_connection(v8::Isolate* isolate, v8::Handle<v8::Object> exports);
+EAPI void register_eldbus_core(v8::Isolate* isolate, v8::Handle<v8::Object> exports);
+EAPI void register_eldbus_message(v8::Isolate* isolate, v8::Handle<v8::Object> exports);
+EAPI void register_eldbus_object_mapper(v8::Isolate* isolate, v8::Handle<v8::Object> exports);
+EAPI void register_eldbus(v8::Isolate* isolate, v8::Handle<v8::Object> exports);
+      
+} } }
+
+#include <eldbus_js_util.hh>
+
+#endif
diff --git a/src/bindings/js/eldbus_js/eldbus_js_connection.cc b/src/bindings/js/eldbus_js/eldbus_js_connection.cc
new file mode 100644 (file)
index 0000000..c02dc8c
--- /dev/null
@@ -0,0 +1,543 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eldbus_Js.hh>
+
+namespace efl { namespace eldbus { namespace js {
+
+namespace {
+      
+v8::Local<v8::Object> wrap_event_callback(Eldbus_Connection *conn,
+                                          Eldbus_Connection_Event_Type type,
+                                          Eldbus_Connection_Event_Cb cb,
+                                          void *cb_data, v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::Value;
+    using v8::Object;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(3);
+    auto ret = obj_tpl->NewInstance();
+
+    ret->Set(compatibility_new<String>(isolate, "_type"),
+             compatibility_new<Integer>(isolate, type));
+
+    compatibility_set_pointer_internal_field(ret, 0, conn);
+    compatibility_set_pointer_internal_field(ret, 1, (void*)(cb));
+    compatibility_set_pointer_internal_field(ret, 2, cb_data);
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        auto o = info.This();
+        auto isolate = info.GetIsolate();
+
+        auto conn
+            = (compatibility_get_pointer_internal_field<Eldbus_Connection*>
+               (o, 0));
+        auto cb
+            = (compatibility_get_pointer_internal_field
+               <Eldbus_Connection_Event_Cb>(o, 1));
+        auto cb_data
+            = (compatibility_get_pointer_internal_field
+               <efl::eina::js::global_ref<Value>*>(o, 2));
+        auto type
+            = (static_cast<Eldbus_Connection_Event_Type>
+               (o->Get(compatibility_new<String>(isolate, "_type"))
+                ->IntegerValue()));
+
+        eldbus_connection_event_callback_del(conn, type, cb, cb_data);
+
+        delete cb_data;
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    return ret;
+}
+
+Eldbus_Connection* extract_eldbus_connection(v8::Local<v8::Object> o)
+{
+    return compatibility_get_pointer_internal_field<Eldbus_Connection*>(o, 0);
+}
+
+void register_timeout_infinite(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name, compatibility_new<Integer>(isolate,
+                                                 ELDBUS_TIMEOUT_INFINITE));
+}
+
+void register_connection_type_unknown(v8::Isolate *isolate,
+                                      v8::Handle<v8::Object> global,
+                                      v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ELDBUS_CONNECTION_TYPE_UNKNOWN));
+}
+
+void register_connection_type_session(v8::Isolate *isolate,
+                                      v8::Handle<v8::Object> global,
+                                      v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ELDBUS_CONNECTION_TYPE_SESSION));
+}
+
+void register_connection_type_system(v8::Isolate *isolate,
+                                     v8::Handle<v8::Object> global,
+                                     v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ELDBUS_CONNECTION_TYPE_SYSTEM));
+}
+
+void register_connection_type_starter(v8::Isolate *isolate,
+                                      v8::Handle<v8::Object> global,
+                                      v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ELDBUS_CONNECTION_TYPE_STARTER));
+}
+
+void register_connection_type_address(v8::Isolate *isolate,
+                                      v8::Handle<v8::Object> global,
+                                      v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ELDBUS_CONNECTION_TYPE_ADDRESS));
+}
+
+void register_connection_type_last(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ELDBUS_CONNECTION_TYPE_LAST));
+}
+
+void register_connection_event_del(v8::Isolate *isolate,
+                                   v8::Handle<v8::Object> global,
+                                   v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name, compatibility_new<Integer>(isolate,
+                                                 ELDBUS_CONNECTION_EVENT_DEL));
+}
+
+void register_connection_event_disconnected(v8::Isolate *isolate,
+                                            v8::Handle<v8::Object> global,
+                                            v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>
+                (isolate, ELDBUS_CONNECTION_EVENT_DISCONNECTED));
+}
+
+void register_connection_event_last(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name, compatibility_new<Integer>(isolate,
+                                                 ELDBUS_CONNECTION_EVENT_LAST));
+}
+
+void register_connection_get(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        Eldbus_Connection_Type type;
+
+        switch (args[0]->IntegerValue()) {
+        case ELDBUS_CONNECTION_TYPE_UNKNOWN:
+            type = ELDBUS_CONNECTION_TYPE_UNKNOWN;
+            break;
+        case ELDBUS_CONNECTION_TYPE_SESSION:
+            type = ELDBUS_CONNECTION_TYPE_SESSION;
+            break;
+        case ELDBUS_CONNECTION_TYPE_SYSTEM:
+            type = ELDBUS_CONNECTION_TYPE_SYSTEM;
+            break;
+        case ELDBUS_CONNECTION_TYPE_STARTER:
+            type = ELDBUS_CONNECTION_TYPE_STARTER;
+            break;
+        case ELDBUS_CONNECTION_TYPE_ADDRESS:
+            type = ELDBUS_CONNECTION_TYPE_ADDRESS;
+            break;
+        case ELDBUS_CONNECTION_TYPE_LAST:
+            type = ELDBUS_CONNECTION_TYPE_LAST;
+            break;
+        default:
+            return compatibility_return();
+        }
+        auto ret = eldbus_connection_get(type);
+        return compatibility_return(wrap_eldbus_connection(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_private_connection_get(v8::Isolate *isolate,
+                                     v8::Handle<v8::Object> global,
+                                     v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsNumber())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        Eldbus_Connection_Type type;
+
+        switch (args[0]->IntegerValue()) {
+        case ELDBUS_CONNECTION_TYPE_UNKNOWN:
+            type = ELDBUS_CONNECTION_TYPE_UNKNOWN;
+            break;
+        case ELDBUS_CONNECTION_TYPE_SESSION:
+            type = ELDBUS_CONNECTION_TYPE_SESSION;
+            break;
+        case ELDBUS_CONNECTION_TYPE_SYSTEM:
+            type = ELDBUS_CONNECTION_TYPE_SYSTEM;
+            break;
+        case ELDBUS_CONNECTION_TYPE_STARTER:
+            type = ELDBUS_CONNECTION_TYPE_STARTER;
+            break;
+        case ELDBUS_CONNECTION_TYPE_ADDRESS:
+            type = ELDBUS_CONNECTION_TYPE_ADDRESS;
+            break;
+        case ELDBUS_CONNECTION_TYPE_LAST:
+            type = ELDBUS_CONNECTION_TYPE_LAST;
+            break;
+        default:
+            return compatibility_return();
+        }
+        auto ret = eldbus_private_connection_get(type);
+        return compatibility_return(wrap_eldbus_connection(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_address_connection_get(v8::Isolate *isolate,
+                                     v8::Handle<v8::Object> global,
+                                     v8::Handle<v8::String> name)
+
+{
+    using v8::String;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsString())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+
+        auto ret = eldbus_address_connection_get(*String::Utf8Value(args[0]));
+        return compatibility_return(wrap_eldbus_connection(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_private_address_connection_get(v8::Isolate *isolate,
+                                             v8::Handle<v8::Object> global,
+                                             v8::Handle<v8::String> name)
+
+{
+    using v8::String;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsString())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+
+        String::Utf8Value address(args[0]);
+
+        auto ret = eldbus_private_address_connection_get(*address);
+        return compatibility_return(wrap_eldbus_connection(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+}
+
+v8::Local<v8::Object> wrap_eldbus_connection(Eldbus_Connection *conn,
+                                             v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::Boolean;
+    using v8::Value;
+    using v8::Handle;
+    using v8::ObjectTemplate;
+    using v8::Function;
+    using v8::FunctionTemplate;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto event_callback_add = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 2 || !info[0]->IsNumber()
+            || !info[1]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = info.GetIsolate();
+        auto conn = extract_eldbus_connection(info.This());
+        Eldbus_Connection_Event_Type type;
+
+        switch (info[0]->IntegerValue()) {
+        case ELDBUS_CONNECTION_EVENT_DEL:
+            type = ELDBUS_CONNECTION_EVENT_DEL;
+            break;
+        case ELDBUS_CONNECTION_EVENT_DISCONNECTED:
+            type = ELDBUS_CONNECTION_EVENT_DISCONNECTED;
+            break;
+        case ELDBUS_CONNECTION_EVENT_LAST:
+            type = ELDBUS_CONNECTION_EVENT_LAST;
+            break;
+        default:
+            return compatibility_return();
+        }
+
+        unique_ptr<persistent_t> cb_data{new persistent_t{isolate, info[1]}};
+
+        auto cb = [](void *data, Eldbus_Connection *conn,
+                     void */*event_info*/) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args{wrap_eldbus_connection(conn, isolate)};
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+        };
+
+        eldbus_connection_event_callback_add(conn, type, cb, cb_data.get());
+        auto ret = wrap_event_callback(conn, type, cb, cb_data.release(),
+                                       isolate);
+        return compatibility_return(ret, info);
+    };
+
+    auto send = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 3 || !info[0]->IsObject() || !info[1]->IsFunction()
+            || !info[2]->IsNumber()) {
+            return compatibility_return();
+        }
+
+        auto isolate = info.GetIsolate();
+        auto conn = extract_eldbus_connection(info.This());
+        auto msg
+            = (compatibility_get_pointer_internal_field<Eldbus_Message*>
+               (info[0]->ToObject(), 0));
+
+        unique_ptr<persistent_t> cb_data{new persistent_t{isolate, info[1]}};
+
+        auto cb = [](void *data, const Eldbus_Message *msg,
+                     Eldbus_Pending *pending) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_const_eldbus_msg(msg, isolate),
+                wrap_eldbus_pending(pending, persistent, isolate)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete persistent;
+        };
+
+        auto ret = eldbus_connection_send(conn, msg, cb, cb_data.get(),
+                                          info[2]->NumberValue());
+        return compatibility_return(wrap_eldbus_pending(ret, cb_data.release(),
+                                                        isolate),
+                                    info);
+    };
+
+    auto unique_name_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto conn = extract_eldbus_connection(info.This());
+
+        auto ret = eldbus_connection_unique_name_get(conn);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto object_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 2 || !info[0]->IsString() || !info[1]->IsString())
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto conn = extract_eldbus_connection(info.This());
+
+        auto ret = eldbus_object_get(conn, *String::Utf8Value(info[0]),
+                                     *String::Utf8Value(info[1]));
+        return compatibility_return(wrap_eldbus_object(ret, isolate), info);
+    };
+
+    auto signal_handler_add = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 5 || !info[0]->IsString() || !info[1]->IsString()
+            || !info[2]->IsString() || !info[3]->IsString()
+            || !info[4]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = info.GetIsolate();
+        auto conn = extract_eldbus_connection(info.This());
+
+        unique_ptr<persistent_t> cb_data{new persistent_t{isolate, info[4]}};
+
+        auto cb = [](void *data, const Eldbus_Message *msg) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args{wrap_const_eldbus_msg(msg, isolate)};
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+        };
+
+        auto ret = eldbus_signal_handler_add(conn, *String::Utf8Value(info[0]),
+                                             *String::Utf8Value(info[1]),
+                                             *String::Utf8Value(info[2]),
+                                             *String::Utf8Value(info[3]),
+                                             cb, cb_data.get());
+        auto wrapped_ret = wrap_eldbus_signal_handler(ret, cb_data.release(),
+                                                      isolate);
+        return compatibility_return(wrapped_ret, info);
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "event_callback_add"),
+             compatibility_new<FunctionTemplate>(isolate, event_callback_add)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "send"),
+             compatibility_new<FunctionTemplate>(isolate, send)->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "unique_name_get"),
+             compatibility_new<FunctionTemplate>(isolate, unique_name_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "object_get"),
+             compatibility_new<FunctionTemplate>(isolate, object_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "signal_handler_add"),
+             compatibility_new<FunctionTemplate>(isolate, signal_handler_add)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, conn);
+
+    return ret;
+}
+      
+EAPI
+void register_eldbus_connection(v8::Isolate* isolate, v8::Handle<v8::Object> exports)
+{
+   using v8::String;
+   register_timeout_infinite(isolate, exports,
+                             compatibility_new<String>
+                             (isolate, "ELDBUS_TIMEOUT_INFINITE"));
+   register_connection_type_unknown(isolate, exports,
+                                    compatibility_new<String>
+                                    (isolate, "ELDBUS_CONNECTION_TYPE_UNKNOWN"));
+   register_connection_type_session(isolate, exports,
+                                    compatibility_new<String>
+                                    (isolate, "ELDBUS_CONNECTION_TYPE_SESSION"));
+   register_connection_type_system(isolate, exports,
+                                   compatibility_new<String>
+                                   (isolate, "ELDBUS_CONNECTION_TYPE_SYSTEM"));
+   register_connection_type_starter(isolate, exports,
+                                    compatibility_new<String>
+                                    (isolate, "ELDBUS_CONNECTION_TYPE_STARTER"));
+   register_connection_type_address(isolate, exports,
+                                    compatibility_new<String>
+                                    (isolate, "ELDBUS_CONNECTION_TYPE_ADDRESS"));
+   register_connection_type_last(isolate, exports,
+                                 compatibility_new<String>
+                                 (isolate, "ELDBUS_CONNECTION_TYPE_LAST"));
+   register_connection_event_del(isolate, exports,
+                                 compatibility_new<String>
+                                 (isolate, "ELDBUS_CONNECTION_EVENT_DEL"));
+   register_connection_event_disconnected(isolate, exports,
+                                          compatibility_new<String>
+                                          (isolate,
+                                           "ELDBUS_CONNECTION_EVENT"
+                                           "_DISCONNECTED"));
+   register_connection_event_last(isolate, exports,
+                                  compatibility_new<String>
+                                  (isolate, "ELDBUS_CONNECTION_EVENT_LAST"));
+
+   register_connection_get(isolate, exports,
+                           compatibility_new<String>
+                           (isolate, "connection_get"));
+
+   register_private_connection_get(isolate, exports,
+                                   compatibility_new<String>
+                                   (isolate, "private_connection_get"));
+
+   register_address_connection_get(isolate, exports,
+                                   compatibility_new<String>
+                                   (isolate, "address_connection_get"));
+
+   register_private_address_connection_get(isolate, exports,
+                                           compatibility_new<String>
+                                           (isolate, "private_address_connection_get"));
+}
+
+} } } // namespace efl { namespace eldbus { namespace js {
diff --git a/src/bindings/js/eldbus_js/eldbus_js_core.cc b/src/bindings/js/eldbus_js/eldbus_js_core.cc
new file mode 100644 (file)
index 0000000..e9a8c33
--- /dev/null
@@ -0,0 +1,183 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eldbus_Js.hh>
+
+namespace efl { namespace eldbus { namespace js {
+
+namespace {
+
+void register_init(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                   v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto init = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = eldbus_init();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, init)
+                ->GetFunction());
+}
+
+void register_shutdown(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                       v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto shutdown = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = eldbus_shutdown();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, shutdown)
+                ->GetFunction());
+}
+
+void register_fdo_bus(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                      v8::Handle<v8::String> name)
+{
+    using v8::String;
+    global->Set(name, compatibility_new<String>(isolate, ELDBUS_FDO_BUS));
+}
+
+void register_fdo_path(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                       v8::Handle<v8::String> name)
+{
+    using v8::String;
+    global->Set(name, compatibility_new<String>(isolate, ELDBUS_FDO_PATH));
+}
+
+void register_fdo_interface(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                            v8::Handle<v8::String> name)
+{
+    using v8::String;
+    global->Set(name, compatibility_new<String>(isolate, ELDBUS_FDO_INTERFACE));
+}
+
+void register_fdo_interface_properties(v8::Isolate *isolate,
+                                       v8::Handle<v8::Object> global,
+                                       v8::Handle<v8::String> name)
+{
+    using v8::String;
+    global->Set(name,
+                compatibility_new<String>(isolate,
+                                          ELDBUS_FDO_INTERFACE_PROPERTIES));
+}
+
+void register_fdo_interface_object_manager(v8::Isolate *isolate,
+                                           v8::Handle<v8::Object> global,
+                                           v8::Handle<v8::String> name)
+{
+    using v8::String;
+    global->Set(name,
+                compatibility_new<String>(isolate,
+                                          ELDBUS_FDO_INTERFACE_OBJECT_MANAGER));
+}
+
+void register_fdo_interface_introspectable(v8::Isolate *isolate,
+                                           v8::Handle<v8::Object> global,
+                                           v8::Handle<v8::String> name)
+{
+    using v8::String;
+    global->Set(name,
+                compatibility_new<String>(isolate,
+                                          ELDBUS_FDO_INTERFACE_INTROSPECTABLE));
+}
+
+void register_fdo_inteface_peer(v8::Isolate *isolate,
+                                v8::Handle<v8::Object> global,
+                                v8::Handle<v8::String> name)
+{
+    using v8::String;
+    global->Set(name,
+                compatibility_new<String>(isolate, ELDBUS_FDO_INTEFACE_PEER));
+}
+
+void register_error_pending_canceled(v8::Isolate *isolate,
+                                     v8::Handle<v8::Object> global,
+                                     v8::Handle<v8::String> name)
+{
+    using v8::String;
+    global->Set(name,
+                compatibility_new<String>(isolate,
+                                          ELDBUS_ERROR_PENDING_CANCELED));
+}
+
+void register_error_pending_timeout(v8::Isolate *isolate,
+                                    v8::Handle<v8::Object> global,
+                                    v8::Handle<v8::String> name)
+{
+    using v8::String;
+    global->Set(name,
+                compatibility_new<String>(isolate,
+                                          ELDBUS_ERROR_PENDING_TIMEOUT));
+}
+
+}
+
+EAPI
+void register_eldbus_core(v8::Isolate* isolate, v8::Handle<v8::Object> exports)
+{
+   using v8::String;
+   register_init(isolate, exports,
+                 compatibility_new<String>(isolate, "eldbus_init"));
+   register_shutdown(isolate, exports,
+                     compatibility_new<String>(isolate, "eldbus_shutdown"));
+   register_fdo_bus(isolate, exports,
+                    compatibility_new<String>(isolate, "ELDBUS_FDO_BUS"));
+   register_fdo_path(isolate, exports,
+                     compatibility_new<String>(isolate, "ELDBUS_FDO_PATH"));
+   register_fdo_interface(isolate, exports,
+                          compatibility_new<String>(isolate,
+                                                    "ELDBUS_FDO_INTERFACE"));
+   register_fdo_interface_properties(isolate, exports,
+                                     compatibility_new<String>
+                                     (isolate,
+                                      "ELDBUS_FDO_INTERFACE_PROPERTIES"));
+   register_fdo_interface_object_manager(isolate, exports,
+                                         compatibility_new<String>
+                                         (isolate, "ELDBUS_FDO_INTERFACE_OBJECT_MANAGER"));
+   
+   register_fdo_interface_introspectable
+     (isolate, exports,
+      compatibility_new<String>(isolate,
+                                "ELDBUS_FDO_INTERFACE_INTROSPECTABLE"));
+   register_fdo_inteface_peer(isolate, exports,
+                              compatibility_new<String>
+                              (isolate, "ELDBUS_FDO_INTEFACE_PEER"));
+   register_error_pending_canceled
+     (isolate, exports,
+      compatibility_new<String>(isolate, "ELDBUS_ERROR_PENDING_CANCELED"));
+   register_error_pending_timeout
+     (isolate, exports,
+      compatibility_new<String>(isolate, "ELDBUS_ERROR_PENDING_TIMEOUT"));
+}
+
+EAPI void register_eldbus(v8::Isolate* isolate, v8::Handle<v8::Object> exports)
+{
+  register_eldbus_connection(isolate, exports);
+  register_eldbus_core(isolate, exports);
+  register_eldbus_message(isolate, exports);
+  register_eldbus_object_mapper(isolate, exports);
+}
+      
+} } } // namespace efl { namespace eldbus { namespace js {
diff --git a/src/bindings/js/eldbus_js/eldbus_js_message.cc b/src/bindings/js/eldbus_js/eldbus_js_message.cc
new file mode 100644 (file)
index 0000000..f9cfa40
--- /dev/null
@@ -0,0 +1,103 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eldbus_Js.hh>
+
+namespace efl { namespace eldbus { namespace js {
+
+namespace {
+
+void register_message_method_call_new(v8::Isolate *isolate,
+                                      v8::Handle<v8::Object> global,
+                                      v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 4 || !args[0]->IsString() || !args[1]->IsString()
+            || !args[2]->IsString() || !args[3]->IsString()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+        auto ret = eldbus_message_method_call_new(*String::Utf8Value(args[0]),
+                                                  *String::Utf8Value(args[1]),
+                                                  *String::Utf8Value(args[2]),
+                                                  *String::Utf8Value(args[3]));
+        return compatibility_return(wrap_eldbus_msg(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_message_error_new(v8::Isolate *isolate,
+                                v8::Handle<v8::Object> global,
+                                v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 3 || !args[0]->IsObject() || !args[1]->IsString()
+            || !args[2]->IsString()) {
+            return compatibility_return();
+        }
+
+        auto isolate = args.GetIsolate();
+        auto ret = eldbus_message_error_new(extract_eldbus_msg(args[0]
+                                                               ->ToObject()),
+                                            *String::Utf8Value(args[1]),
+                                            *String::Utf8Value(args[2]));
+        return compatibility_return(wrap_eldbus_msg(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+void register_message_method_return_new(v8::Isolate *isolate,
+                                        v8::Handle<v8::Object> global,
+                                        v8::Handle<v8::String> name)
+{
+    using v8::String;
+    using v8::FunctionTemplate;
+
+    auto f = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsObject())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto eldbus_msg = extract_eldbus_msg(args[0]->ToObject());
+        auto ret = eldbus_message_method_return_new(eldbus_msg);
+        return compatibility_return(wrap_eldbus_msg(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, f)->GetFunction());
+}
+
+}
+
+EAPI
+void register_eldbus_message(v8::Isolate* isolate, v8::Handle<v8::Object> exports)
+{
+  register_message_method_call_new
+    (isolate, exports, compatibility_new<v8::String>
+     (isolate, "message_method_call_new"));
+
+  register_message_error_new
+    (isolate, exports, compatibility_new<v8::String>
+     (isolate, "message_error_new"));
+
+  register_message_method_return_new
+    (isolate, exports, compatibility_new<v8::String>
+     (isolate, "message_method_return_new"));
+}
+
+} } } // namespace efl { namespace eldbus { namespace js {
diff --git a/src/bindings/js/eldbus_js/eldbus_js_object_mapper.cc b/src/bindings/js/eldbus_js/eldbus_js_object_mapper.cc
new file mode 100644 (file)
index 0000000..955ce80
--- /dev/null
@@ -0,0 +1,100 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eldbus_Js.hh>
+
+namespace efl { namespace eldbus { namespace js {
+
+namespace {
+      
+void register_object_event_iface_added(v8::Isolate *isolate,
+                                       v8::Handle<v8::Object> global,
+                                       v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ELDBUS_OBJECT_EVENT_IFACE_ADDED));
+}
+
+void register_object_event_iface_removed(v8::Isolate *isolate,
+                                         v8::Handle<v8::Object> global,
+                                         v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate,
+                                           ELDBUS_OBJECT_EVENT_IFACE_REMOVED));
+}
+
+void register_object_event_property_changed(v8::Isolate *isolate,
+                                            v8::Handle<v8::Object> global,
+                                            v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>
+                (isolate, ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED));
+}
+
+void register_object_event_property_removed(v8::Isolate *isolate,
+                                            v8::Handle<v8::Object> global,
+                                            v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>
+                (isolate, ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED));
+}
+
+void register_object_event_del(v8::Isolate *isolate,
+                               v8::Handle<v8::Object> global,
+                               v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ELDBUS_OBJECT_EVENT_DEL));
+}
+
+void register_object_event_last(v8::Isolate *isolate,
+                                v8::Handle<v8::Object> global,
+                                v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    global->Set(name,
+                compatibility_new<Integer>(isolate, ELDBUS_OBJECT_EVENT_LAST));
+}
+
+}
+
+EAPI
+void register_eldbus_object_mapper(v8::Isolate* isolate, v8::Handle<v8::Object> exports)
+{
+  register_object_event_iface_added
+    (isolate, exports, compatibility_new<v8::String>
+     (isolate, "object_event_iface_added"));
+
+  register_object_event_iface_removed
+    (isolate, exports, compatibility_new<v8::String>
+     (isolate, "object_event_iface_removed"));
+
+  register_object_event_property_changed
+    (isolate, exports, compatibility_new<v8::String>
+     (isolate, "object_event_property_changed"));
+
+  register_object_event_property_removed
+    (isolate, exports, compatibility_new<v8::String>
+     (isolate, "object_event_property_removed"));
+
+  register_object_event_del
+    (isolate, exports, compatibility_new<v8::String>
+     (isolate, "object_event_del"));
+
+  register_object_event_last
+    (isolate, exports, compatibility_new<v8::String>
+     (isolate, "object_event_last"));
+}
+
+
+} } } // namespace efl { namespace eldbus { namespace js {
diff --git a/src/bindings/js/eldbus_js/eldbus_js_util.hh b/src/bindings/js/eldbus_js/eldbus_js_util.hh
new file mode 100644 (file)
index 0000000..c5af575
--- /dev/null
@@ -0,0 +1,836 @@
+#ifndef ELDBUS_JS_UTIL_HH
+#define ELDBUS_JS_UTIL_HH
+
+namespace efl { namespace eldbus { namespace js {
+
+using eina::js::compatibility_get_pointer_internal_field;
+using eina::js::compatibility_set_pointer_internal_field;
+using eina::js::compatibility_new;
+using eina::js::compatibility_callback_info_type;
+using eina::js::compatibility_return_type;
+using eina::js::compatibility_return;
+      
+v8::Local<v8::Object> wrap_eldbus_connection(Eldbus_Connection *conn,
+                                             v8::Isolate *isolate);
+
+inline
+const Eldbus_Message *extract_const_eldbus_msg(v8::Local<v8::Object> o)
+{
+    return compatibility_get_pointer_internal_field<Eldbus_Message*>(o, 0);
+}
+
+inline
+v8::Local<v8::Object> wrap_const_eldbus_msg(const Eldbus_Message *msg,
+                                            v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::Object;
+    using v8::Boolean;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto path_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto msg = extract_const_eldbus_msg(info.This());
+
+        auto ret = eldbus_message_path_get(msg);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto interface_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto msg = extract_const_eldbus_msg(info.This());
+
+        auto ret = eldbus_message_interface_get(msg);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto member_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto msg = extract_const_eldbus_msg(info.This());
+
+        auto ret = eldbus_message_member_get(msg);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto destination_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto msg = extract_const_eldbus_msg(info.This());
+
+        auto ret = eldbus_message_destination_get(msg);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto sender_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto msg = extract_const_eldbus_msg(info.This());
+
+        auto ret = eldbus_message_sender_get(msg);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto signature_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto msg = extract_const_eldbus_msg(info.This());
+
+        auto ret = eldbus_message_signature_get(msg);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto error_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto msg = extract_const_eldbus_msg(info.This());
+        const char *name = NULL;
+        const char *text = NULL;
+        auto ret = compatibility_new<Object>(isolate);
+
+        auto bret = eldbus_message_error_get(msg, &name, &text);
+        ret->Set(compatibility_new<String>(isolate, "ok"),
+                 compatibility_new<Boolean>(isolate, bret));
+
+        if (bret) {
+            ret->Set(compatibility_new<String>(isolate, "name"),
+                     compatibility_new<String>(isolate, name));
+            ret->Set(compatibility_new<String>(isolate, "text"),
+                     compatibility_new<String>(isolate, text));
+        }
+
+        return compatibility_return(ret, info);
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "path_get"),
+             compatibility_new<FunctionTemplate>(isolate, path_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "interface_get"),
+             compatibility_new<FunctionTemplate>(isolate, interface_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "member_get"),
+             compatibility_new<FunctionTemplate>(isolate, member_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "destination_get"),
+             compatibility_new<FunctionTemplate>(isolate, destination_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "sender_get"),
+             compatibility_new<FunctionTemplate>(isolate, sender_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "signature_get"),
+             compatibility_new<FunctionTemplate>(isolate, signature_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "error_get"),
+             compatibility_new<FunctionTemplate>(isolate, error_get)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0,
+                                             const_cast<Eldbus_Message*>(msg));
+
+    return ret;
+}
+
+inline Eldbus_Message *extract_eldbus_msg(v8::Local<v8::Object> o)
+{
+    return compatibility_get_pointer_internal_field<Eldbus_Message*>(o, 0);
+}
+
+inline
+v8::Local<v8::Object> wrap_eldbus_msg(Eldbus_Message *msg, v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::FunctionTemplate;
+
+    auto ret = wrap_const_eldbus_msg(msg, isolate);
+
+    auto ref = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto msg = extract_eldbus_msg(info.This());
+
+        eldbus_message_ref(msg);
+
+        return compatibility_return();
+    };
+
+    auto unref = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto msg = extract_eldbus_msg(info.This());
+
+        eldbus_message_unref(msg);
+
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "ref"),
+             compatibility_new<FunctionTemplate>(isolate, ref)->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "unref"),
+             compatibility_new<FunctionTemplate>(isolate, unref)
+             ->GetFunction());
+
+    return ret;
+}
+
+inline
+v8::Local<v8::Object> wrap_eldbus_pending(Eldbus_Pending *pending,
+                                          efl::eina::js::global_ref<v8::Value>*
+                                          persistent,
+                                          v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::Object;
+    using v8::Boolean;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    typedef decltype(persistent) persistent_ptr_t;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(2);
+    auto ret = obj_tpl->NewInstance();
+
+    auto cancel = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto o = info.This();
+        auto pending
+            = compatibility_get_pointer_internal_field<Eldbus_Pending*>(o, 0);
+        auto persistent
+            = compatibility_get_pointer_internal_field<persistent_ptr_t>(o, 1);
+
+        eldbus_pending_cancel(pending);
+        delete persistent;
+        return compatibility_return();
+    };
+
+    auto destination_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto o = info.This();
+        auto pending
+            = compatibility_get_pointer_internal_field<Eldbus_Pending*>(o, 0);
+
+        auto ret = eldbus_pending_destination_get(pending);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto path_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto o = info.This();
+        auto pending
+            = compatibility_get_pointer_internal_field<Eldbus_Pending*>(o, 0);
+
+        auto ret = eldbus_pending_path_get(pending);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto interface_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto o = info.This();
+        auto pending
+            = compatibility_get_pointer_internal_field<Eldbus_Pending*>(o, 0);
+
+        auto ret = eldbus_pending_interface_get(pending);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto method_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto o = info.This();
+        auto pending
+            = compatibility_get_pointer_internal_field<Eldbus_Pending*>(o, 0);
+
+        auto ret = eldbus_pending_method_get(pending);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "cancel"),
+             compatibility_new<FunctionTemplate>(isolate, cancel)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "destination_get"),
+             compatibility_new<FunctionTemplate>(isolate, destination_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "path_get"),
+             compatibility_new<FunctionTemplate>(isolate, path_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "interface_get"),
+             compatibility_new<FunctionTemplate>(isolate, interface_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "method_get"),
+             compatibility_new<FunctionTemplate>(isolate, method_get)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, pending);
+    compatibility_set_pointer_internal_field(ret, 1, persistent);
+
+    return ret;
+}
+
+inline
+v8::Local<v8::Object>
+wrap_eldbus_signal_handler(Eldbus_Signal_Handler *handler,
+                           efl::eina::js::global_ref<v8::Value> *persistent,
+                           v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::Object;
+    using v8::Boolean;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    typedef decltype(persistent) persistent_ptr_t;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(2);
+    auto ret = obj_tpl->NewInstance();
+
+    auto ref = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto o = info.This();
+        auto handler
+            = (compatibility_get_pointer_internal_field<Eldbus_Signal_Handler*>
+               (o, 0));
+
+        eldbus_signal_handler_ref(handler);
+        return compatibility_return();
+    };
+
+    auto unref = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto o = info.This();
+        auto handler
+            = (compatibility_get_pointer_internal_field<Eldbus_Signal_Handler*>
+               (o, 0));
+
+        eldbus_signal_handler_unref(handler);
+        return compatibility_return();
+    };
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto o = info.This();
+        auto handler
+            = (compatibility_get_pointer_internal_field<Eldbus_Signal_Handler*>
+               (o, 0));
+        auto persistent
+            = compatibility_get_pointer_internal_field<persistent_ptr_t>(o, 1);
+
+        eldbus_signal_handler_del(handler);
+        delete persistent;
+        return compatibility_return();
+    };
+
+    auto sender_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto o = info.This();
+        auto handler
+            = (compatibility_get_pointer_internal_field<Eldbus_Signal_Handler*>
+               (o, 0));
+
+        auto ret = eldbus_signal_handler_sender_get(handler);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto path_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto o = info.This();
+        auto handler
+            = (compatibility_get_pointer_internal_field<Eldbus_Signal_Handler*>
+               (o, 0));
+
+        auto ret = eldbus_signal_handler_path_get(handler);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto interface_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto o = info.This();
+        auto handler
+            = (compatibility_get_pointer_internal_field<Eldbus_Signal_Handler*>
+               (o, 0));
+
+        auto ret = eldbus_signal_handler_interface_get(handler);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto member_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto o = info.This();
+        auto handler
+            = (compatibility_get_pointer_internal_field<Eldbus_Signal_Handler*>
+               (o, 0));
+
+        auto ret = eldbus_signal_handler_member_get(handler);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto match_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto o = info.This();
+        auto handler
+            = (compatibility_get_pointer_internal_field<Eldbus_Signal_Handler*>
+               (o, 0));
+
+        auto ret = eldbus_signal_handler_match_get(handler);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto connection_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto o = info.This();
+        auto handler
+            = (compatibility_get_pointer_internal_field<Eldbus_Signal_Handler*>
+               (o, 0));
+
+        auto ret = eldbus_signal_handler_connection_get(handler);
+        return compatibility_return(wrap_eldbus_connection(ret, isolate), info);
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "ref"),
+             compatibility_new<FunctionTemplate>(isolate, ref)->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "unref"),
+             compatibility_new<FunctionTemplate>(isolate, unref)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "sender_get"),
+             compatibility_new<FunctionTemplate>(isolate, sender_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "path_get"),
+             compatibility_new<FunctionTemplate>(isolate, path_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "interface_get"),
+             compatibility_new<FunctionTemplate>(isolate, interface_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "member_get"),
+             compatibility_new<FunctionTemplate>(isolate, member_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "match_get"),
+             compatibility_new<FunctionTemplate>(isolate, match_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "connection_get"),
+             compatibility_new<FunctionTemplate>(isolate, connection_get)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, handler);
+    compatibility_set_pointer_internal_field(ret, 1, persistent);
+
+    return ret;
+}
+
+static
+v8::Local<v8::Object> wrap_object_event_callback(Eldbus_Object *obj,
+                                                 Eldbus_Object_Event_Type type,
+                                                 Eldbus_Object_Event_Cb cb,
+                                                 void *cb_data,
+                                                 v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::Integer;
+    using v8::Value;
+    using v8::Object;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(3);
+    auto ret = obj_tpl->NewInstance();
+
+    ret->Set(compatibility_new<String>(isolate, "_type"),
+             compatibility_new<Integer>(isolate, type));
+
+    compatibility_set_pointer_internal_field(ret, 0, obj);
+    compatibility_set_pointer_internal_field(ret, 1, (void*)(cb));
+    compatibility_set_pointer_internal_field(ret, 2, cb_data);
+
+    auto del = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        auto o = info.This();
+        auto isolate = info.GetIsolate();
+
+        auto obj
+            = (compatibility_get_pointer_internal_field<Eldbus_Object*>
+               (o, 0));
+        auto cb
+            = (compatibility_get_pointer_internal_field
+               <Eldbus_Object_Event_Cb>(o, 1));
+        auto cb_data
+            = (compatibility_get_pointer_internal_field
+               <efl::eina::js::global_ref<Value>*>(o, 2));
+        auto type
+            = (static_cast<Eldbus_Object_Event_Type>
+               (o->Get(compatibility_new<String>(isolate, "_type"))
+                ->IntegerValue()));
+
+        eldbus_object_event_callback_del(obj, type, cb, cb_data);
+
+        delete cb_data;
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "del"),
+             compatibility_new<FunctionTemplate>(isolate, del)->GetFunction());
+
+    return ret;
+}
+
+inline
+Eldbus_Object *extract_eldbus_object(v8::Local<v8::Object> o)
+{
+    return compatibility_get_pointer_internal_field<Eldbus_Object*>(o, 0);
+}
+
+inline
+v8::Local<v8::Object> wrap_eldbus_object(Eldbus_Object *object,
+                                         v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::Value;
+    using v8::Handle;
+    using v8::Function;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto ref = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto object = extract_eldbus_object(info.This());
+
+        eldbus_object_ref(object);
+        return compatibility_return();
+    };
+
+    auto unref = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto object = extract_eldbus_object(info.This());
+
+        eldbus_object_unref(object);
+        return compatibility_return();
+    };
+
+    auto event_callback_add = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 2 || !info[0]->IsNumber()
+            || !info[1]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        Eldbus_Object_Event_Type type;
+
+        switch (info[0]->IntegerValue()) {
+        case ELDBUS_OBJECT_EVENT_IFACE_ADDED:
+            type = ELDBUS_OBJECT_EVENT_IFACE_ADDED;
+            break;
+        case ELDBUS_OBJECT_EVENT_IFACE_REMOVED:
+            type = ELDBUS_OBJECT_EVENT_IFACE_REMOVED;
+            break;
+        case ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED:
+            type = ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED;
+            break;
+        case ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED:
+            type = ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED;
+            break;
+        case ELDBUS_OBJECT_EVENT_DEL:
+            type = ELDBUS_OBJECT_EVENT_DEL;
+            break;
+        case ELDBUS_OBJECT_EVENT_LAST:
+            type = ELDBUS_OBJECT_EVENT_LAST;
+            break;
+        default:
+            return compatibility_return();
+        }
+
+        auto isolate = info.GetIsolate();
+
+        unique_ptr<persistent_t> cb_data{new persistent_t{isolate, info[1]}};
+
+        auto cb = [](void *data, Eldbus_Object *obj, void */*event_info*/) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args{wrap_eldbus_object(obj, isolate)};
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+        };
+
+        auto object = extract_eldbus_object(info.This());
+
+        eldbus_object_event_callback_add(object, type, cb, cb_data.get());
+        auto ret = wrap_object_event_callback(object, type, cb,
+                                              cb_data.release(), isolate);
+        return compatibility_return(ret, info);
+    };
+
+    auto connection_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto object = extract_eldbus_object(info.This());
+
+        auto conn = eldbus_object_connection_get(object);
+        return compatibility_return(wrap_eldbus_connection(conn, isolate),
+                                    info);
+    };
+
+    auto bus_name_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto object = extract_eldbus_object(info.This());
+
+        auto ret = eldbus_object_bus_name_get(object);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto path_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto object = extract_eldbus_object(info.This());
+
+        auto ret = eldbus_object_path_get(object);
+        return compatibility_return(compatibility_new<String>(isolate, ret),
+                                    info);
+    };
+
+    auto send = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 3 || !info[0]->IsObject() || !info[1]->IsFunction()
+            || !info[2]->IsNumber()) {
+            return compatibility_return();
+        }
+
+        auto isolate = info.GetIsolate();
+        auto obj = extract_eldbus_object(info.This());
+        auto msg
+            = (compatibility_get_pointer_internal_field<Eldbus_Message*>
+               (info[0]->ToObject(), 0));
+
+        unique_ptr<persistent_t> cb_data{new persistent_t{isolate, info[1]}};
+
+        auto cb = [](void *data, const Eldbus_Message *msg,
+                     Eldbus_Pending *pending) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_const_eldbus_msg(msg, isolate),
+                wrap_eldbus_pending(pending, persistent, isolate)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+
+            delete persistent;
+        };
+
+        auto ret = eldbus_object_send(obj, msg, cb, cb_data.get(),
+                                      info[2]->NumberValue());
+        return compatibility_return(wrap_eldbus_pending(ret, cb_data.release(),
+                                                        isolate),
+                                    info);
+    };
+
+    auto signal_handler_add = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 3 || !info[0]->IsString() || !info[1]->IsString()
+            || !info[2]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = info.GetIsolate();
+        auto object = extract_eldbus_object(info.This());
+        String::Utf8Value interface(info[0]);
+        String::Utf8Value member(info[1]);
+
+        unique_ptr<persistent_t> cb_data{new persistent_t{isolate, info[2]}};
+
+        auto cb = [](void *data, const Eldbus_Message *msg) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args{wrap_const_eldbus_msg(msg, isolate)};
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+        };
+
+        auto ret = eldbus_object_signal_handler_add(object, *interface, *member,
+                                                    cb, cb_data.get());
+        return
+            compatibility_return(wrap_eldbus_signal_handler(ret,
+                                                            cb_data.release(),
+                                                            isolate),
+                                 info);
+    };
+
+    auto method_call_new = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 2 || !info[0]->IsString()
+            || !info[1]->IsString()) {
+            return compatibility_return();
+        }
+
+        auto isolate = info.GetIsolate();
+        auto object = extract_eldbus_object(info.This());
+        auto ret = eldbus_object_method_call_new(object,
+                                                 *String::Utf8Value(info[0]),
+                                                 *String::Utf8Value(info[1]));
+        return compatibility_return(wrap_eldbus_msg(ret, isolate), info);
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "ref"),
+             compatibility_new<FunctionTemplate>(isolate, ref)->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "unref"),
+             compatibility_new<FunctionTemplate>(isolate, unref)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "event_callback_add"),
+             compatibility_new<FunctionTemplate>(isolate, event_callback_add)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "connection_get"),
+             compatibility_new<FunctionTemplate>(isolate, connection_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "bus_name_get"),
+             compatibility_new<FunctionTemplate>(isolate, bus_name_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "path_get"),
+             compatibility_new<FunctionTemplate>(isolate, path_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "send"),
+             compatibility_new<FunctionTemplate>(isolate, send)->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "signal_handler_add"),
+             compatibility_new<FunctionTemplate>(isolate, signal_handler_add)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "method_call_new"),
+             compatibility_new<FunctionTemplate>(isolate, method_call_new)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, object);
+
+    return ret;
+}
+
+} } } // namespace efl { namespace eldbus { namespace js {
+
+#endif /* ELDBUS_JS_UTIL_HH */
diff --git a/src/bindings/js/eo_js/Eo_Js.hh b/src/bindings/js/eo_js/Eo_Js.hh
new file mode 100644 (file)
index 0000000..ab08b98
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef EFL_EO_JS_HH
+#define EFL_EO_JS_HH
+
+#include <Eina_Js.hh>
+
+#include <eo_js_direction.hh>
+#include <eo_js_constructor.hh>
+#include <eo_js_call_function.hh>
+#include <eo_js_event.hh>
+#include <eo_js_namespace.hh>
+#include <eo_js_struct.hh>
+#include <eo_js_construct_from_eo.hh>
+
+#endif
+
diff --git a/src/bindings/js/eo_js/eo_js_call_function.hh b/src/bindings/js/eo_js/eo_js_call_function.hh
new file mode 100644 (file)
index 0000000..26bf03f
--- /dev/null
@@ -0,0 +1,288 @@
+#ifndef EFL_EO_JS_CALL_FUNCTION_HH
+#define EFL_EO_JS_CALL_FUNCTION_HH
+
+#include <eina_tuple.hh>
+#include <eina_tuple_c.hh>
+#include <eina_function.hh>
+
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <cassert>
+#include <vector>
+
+namespace efl { namespace eo { namespace js {
+
+inline eina::js::compatibility_return_type call_function(eina::js::compatibility_callback_info_type args)
+{
+  void* data = v8::External::Cast(*args.Data())->Value();
+  std::function<eina::js::compatibility_return_type(eina::js::compatibility_callback_info_type)>*
+    f = static_cast<std::function<eina::js::compatibility_return_type(eina::js::compatibility_callback_info_type)>*>(data);
+  return (*f)(args);
+}
+
+template <typename In, std::size_t I>
+struct is_in : eina::_mpl::tuple_contains<std::integral_constant<std::size_t, I>, In>
+{};
+
+template <typename In, std::size_t I>
+struct arg_index : std::integral_constant<std::size_t,
+  std::conditional<is_in<In, I>::value, std::integral_constant<std::size_t, 1>, std::integral_constant<std::size_t, 0>>::type::value +
+  arg_index<In, I - 1>::value>
+{};
+
+template <typename In>
+struct arg_index<In, 0> : std::integral_constant<std::size_t, 0>
+{};
+
+template <typename In, typename Out, typename Ownership, typename F, typename Return, typename Parameters>
+struct method_caller
+{
+  typedef typename eina::_mpl::function_params<F>::type parameters_t;
+
+  template <std::size_t I>
+  struct is_out : eina::_mpl::tuple_contains<std::integral_constant<std::size_t, I>, Out>
+  {};
+
+  template <std::size_t I>
+  struct is_inout : std::integral_constant<bool,
+    eina::_mpl::tuple_contains<std::integral_constant<std::size_t, I>, Out>::value &&
+    eina::_mpl::tuple_contains<std::integral_constant<std::size_t, I>, In>::value>
+  {};
+
+  template <std::size_t I, typename Outs>
+  static
+  typename std::tuple_element<I, parameters_t>::type
+  get_value(eina::js::compatibility_callback_info_type args, Outs& /*outs*/, v8::Isolate* isolate, char const* class_name
+            , std::false_type)
+  {
+    using Param = typename std::tuple_element<I, Parameters>::type;
+    const auto js_index = arg_index<In, I>::value;
+
+    return eina::js::get_value_from_javascript
+      (args[js_index], isolate, class_name, eina::js::value_tag<Param>());
+  }
+
+  template <std::size_t I, typename Outs>
+  static
+  typename std::add_pointer<
+  typename std::tuple_element
+    <eina::_mpl::tuple_find<std::integral_constant<std::size_t, I>, Out>::value
+     , Outs>::type>::type
+  get_value(eina::js::compatibility_callback_info_type, Outs& outs, v8::Isolate*, char const*
+            , std::true_type)
+  {
+    return &std::get<eina::_mpl::tuple_find<std::integral_constant<std::size_t, I>, Out>::value>
+      (outs);
+  }
+
+  template <typename OutParameter, std::size_t I, typename R>
+  eina::js::compatibility_return_type
+  create_return_unique_value(eina::js::compatibility_callback_info_type args
+                             , R const& r) const
+  {
+    return eina::js::compatibility_return(
+      eina::js::get_value_from_c(
+        eina::js::wrap_value<OutParameter>(r, eina::js::value_tag<OutParameter>{}),
+        args.GetIsolate(),
+        class_names[I]),
+      args);
+  }
+
+  template <typename OutParameters, typename Outs>
+  eina::js::compatibility_return_type
+  create_return_value(eina::js::compatibility_callback_info_type args
+                      , Outs const& outs
+                      , typename std::enable_if<std::tuple_size<Outs>::value == 1>::type* = 0) const
+  {
+    using OutParameter = typename std::tuple_element<0, OutParameters>::type;
+    return create_return_unique_value<OutParameter, std::tuple_element<0, Out>::type::value>(args, std::get<0u>(outs));
+  }
+
+  template <typename OutParameters, typename Outs>
+  eina::js::compatibility_return_type
+  create_return_value(eina::js::compatibility_callback_info_type
+                      , Outs const&
+                      , typename std::enable_if<std::tuple_size<Outs>::value == 0>::type* = 0) const
+  {
+    // nothing
+    return eina::js::compatibility_return();
+  }
+
+  template <typename OutParameters, typename Outs>
+  eina::js::compatibility_return_type
+  create_return_value(eina::js::compatibility_callback_info_type args
+                      , Outs const& outs
+                      , typename std::enable_if<(std::tuple_size<Outs>::value > 1)>::type* = 0) const
+  {
+    v8::Isolate* isolate = args.GetIsolate();
+    int const length = std::tuple_size<Outs>::value;
+    v8::Local<v8::Array> ret = eina::js::compatibility_new<v8::Array>(isolate, length);
+    set_return<OutParameters, 0u>(isolate, ret, outs, eina::make_index_sequence<std::tuple_size<Outs>::value>());
+    return eina::js::compatibility_return(ret, args);
+  }
+
+  template <typename OutParameters, typename R, typename Outs>
+  eina::js::compatibility_return_type
+  create_return_value(eina::js::compatibility_callback_info_type args
+                      , R const& r
+                      , Outs const&
+                      , typename std::enable_if<std::tuple_size<Outs>::value == 0>::type* = 0) const
+  {
+    return create_return_unique_value<Return, std::tuple_size<Ownership>::value>(args, r);
+  }
+
+  template <typename OutParameters, std::size_t Offset, typename Outs, std::size_t...S>
+  void set_return(v8::Isolate* isolate, v8::Local<v8::Array> r
+                  , Outs const& outs, eina::index_sequence<S...>) const
+  {
+    std::initializer_list<int> l
+      = {(r->Set(S+Offset, eina::js::get_value_from_c(
+            eina::js::wrap_value<typename std::tuple_element<S, OutParameters>::type>(std::get<S>(outs), eina::js::value_tag<typename std::tuple_element<S, OutParameters>::type>{}),
+            isolate,
+            class_names[std::tuple_element<S, Out>::type::value])),0)...};
+    static_cast<void>(l);
+  }
+
+  template <typename OutParameters, typename R, typename Outs>
+  eina::js::compatibility_return_type
+  create_return_value(eina::js::compatibility_callback_info_type args
+                      , R const& r
+                      , Outs const& outs
+                      , typename std::enable_if<std::tuple_size<Outs>::value != 0>::type* = 0) const
+  {
+    v8::Isolate* isolate = args.GetIsolate();
+    int const length = std::tuple_size<Outs>::value + 1;
+    v8::Local<v8::Array> ret = eina::js::compatibility_new<v8::Array>(isolate, length);
+    ret->Set(0, eina::js::get_value_from_c(
+      eina::js::wrap_value<Return>(r, eina::js::value_tag<Return>{}),
+      isolate,
+      class_names[std::tuple_size<Ownership>::value]));
+    set_return<OutParameters, 1u>(isolate, ret, outs, eina::make_index_sequence<std::tuple_size<Outs>::value>());
+    return eina::js::compatibility_return(ret, args);
+  }
+
+  template <std::size_t I, typename Outs>
+  static void
+  init_inout(eina::js::compatibility_callback_info_type args
+            , Outs& outs
+            , v8::Isolate* isolate
+            , char const* class_name
+            , std::true_type)
+  {
+    using Param = typename std::remove_pointer<typename std::tuple_element<I, Parameters>::type>::type;
+
+    const auto js_index = arg_index<In, I>::value;
+
+    *get_value<I>(args, outs, args.GetIsolate(), class_name, std::true_type()) =
+      eina::js::get_value_from_javascript(args[js_index], isolate, class_name, eina::js::value_tag<Param>());;
+  }
+
+  template <std::size_t I, typename Outs>
+  static void
+  init_inout(eina::js::compatibility_callback_info_type
+            , Outs&
+            , v8::Isolate*
+            , char const*
+            , std::false_type)
+  {
+  }
+
+  template <typename OutParameters, std::size_t... I>
+  eina::js::compatibility_return_type
+  aux(eina::js::compatibility_callback_info_type args, eina::index_sequence<I...>
+      , std::true_type) const
+  {
+    typename eina::_mpl::tuple_transform<Out, out_transform<parameters_t> >::type outs {};
+    static_cast<void>(outs);
+
+    std::initializer_list<int> l =
+      {(init_inout<I>(args, outs, args.GetIsolate(), class_names[I], typename is_inout<I>::type()), 0)...};
+    static_cast<void>(l);
+
+    function(get_value<I>(args, outs, args.GetIsolate(), class_names[I], typename is_out<I>::type())...);
+    return create_return_value<OutParameters>(args, outs);
+  }
+
+  template <typename OutParameters, std::size_t... I>
+  eina::js::compatibility_return_type
+  aux(eina::js::compatibility_callback_info_type args, eina::index_sequence<I...>
+      , std::false_type) const
+  {
+    typename eina::_mpl::tuple_transform<Out, out_transform<parameters_t> >::type outs {};
+    static_cast<void>(outs);
+
+    std::initializer_list<int> l =
+      {(init_inout<I>(args, outs, args.GetIsolate(), class_names[I], typename is_inout<I>::type()), 0)...};
+    static_cast<void>(l);
+
+    typename eina::_mpl::function_return<F>::type r =
+      function(get_value<I>(args, outs, args.GetIsolate(), class_names[I], typename is_out<I>::type())...);
+    return create_return_value<OutParameters>(args, r, outs);
+  }
+
+  template <typename P>
+  struct out_transform
+  {
+    template <typename T>
+    struct apply
+    {
+      typedef typename std::remove_pointer<typename std::tuple_element<T::value, P>::type>::type type;
+    };
+  };
+
+  eina::js::compatibility_return_type operator()(eina::js::compatibility_callback_info_type args)
+  {
+    using OutParameters = typename eina::_mpl::tuple_transform<Out, out_transform<Parameters> >::type;
+
+    int input_parameters = std::tuple_size<In>::value;
+    if(input_parameters <= args.Length())
+      {
+        v8::Local<v8::Object> self = args.This();
+        v8::Local<v8::Value> external = self->GetInternalField(0);
+        Eo* eo = static_cast<Eo*>(v8::External::Cast(*external)->Value());
+        try
+          {
+            eo_do
+              (eo,
+                 aux<OutParameters>(
+                 args,
+                 eina::make_index_sequence<std::tuple_size<parameters_t>::value>(),
+                 std::is_same<void, Return>())
+              );
+          }
+        catch(std::logic_error const&)
+          {
+            return eina::js::compatibility_return();
+          }
+      }
+    else
+      {
+        return eina::js::compatibility_throw
+          (v8::Exception::TypeError
+           (eina::js::compatibility_new<v8::String>(nullptr, "Expected more arguments for this call")));
+      }
+  }
+
+  template <typename A>
+  method_caller(F f, A&& c)
+    : function(f)
+    , class_names(std::forward<A>(c))
+  {}
+
+  F function;
+  /// Hold the names of the type of each argument, with the return's type name at the end
+  std::array<const char*, std::tuple_size<Ownership>::value + 1> class_names;
+};
+
+template <typename In, typename Out, typename Ownership, typename Return, typename Parameters, std::size_t N, typename F>
+v8::Handle<v8::Value> call_function_data(v8::Isolate* isolate, std::array<const char*, N> class_names, F f)
+{
+  return eina::js::compatibility_new<v8::External>
+    (isolate, new std::function<eina::js::compatibility_return_type(eina::js::compatibility_callback_info_type const&)>
+     (method_caller<In, Out, Ownership, F, Return, Parameters>{f, class_names}));
+}
+
+} } }
+
+#endif
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
new file mode 100644 (file)
index 0000000..287aaa7
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef EFL_EO_JS_CONSTRUCT_FROM_EO_HH
+#define EFL_EO_JS_CONSTRUCT_FROM_EO_HH
+
+#include <eina_tuple.hh>
+#include <eina_tuple_c.hh>
+#include <eina_function.hh>
+#include <Eo.h>
+
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <cassert>
+#include <vector>
+
+namespace efl { namespace eo { namespace js {
+
+inline eina::js::compatibility_return_type construct_from_eo(eina::js::compatibility_callback_info_type args)
+{
+  if(args.IsConstructCall())
+    {
+      Eo* eo = static_cast<Eo*>(v8::External::Cast(*args[0])->Value());
+      args.This()->SetInternalField(0, args[0]);
+      efl::eina::js::make_weak(args.GetIsolate(), args.This(), [eo] { eo_unref(eo); });
+      return eina::js::compatibility_return();
+    }
+  else
+    {
+      std::size_t argc = args.Length();
+      std::vector<v8::Local<v8::Value> > argv (argc ? argc : 1 );
+      for(int i = 0; i != args.Length(); ++i)
+        argv[i] = args[i];
+      args.Callee()->NewInstance(argc, &argv[0]);
+      return eina::js::compatibility_return();
+    }
+}
+      
+} } }
+
+#endif
diff --git a/src/bindings/js/eo_js/eo_js_constructor.hh b/src/bindings/js/eo_js/eo_js_constructor.hh
new file mode 100644 (file)
index 0000000..09cc9dc
--- /dev/null
@@ -0,0 +1,136 @@
+#ifndef EFL_EO_JS_CONSTRUCTOR_HH
+#define EFL_EO_JS_CONSTRUCTOR_HH
+
+#include <Eina.hh>
+
+#include <eina_tuple.hh>
+#include <eina_function.hh>
+#include <Eo.h>
+
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <cassert>
+#include <vector>
+
+namespace efl { namespace eo { namespace js {
+
+inline eina::js::compatibility_return_type constructor(eina::js::compatibility_callback_info_type args)
+{
+  if(args.IsConstructCall())
+    {
+      void* data = v8::External::Cast(*args.Data())->Value();
+      std::function<eina::js::compatibility_return_type(eina::js::compatibility_callback_info_type)>*
+        f = static_cast<std::function<eina::js::compatibility_return_type(eina::js::compatibility_callback_info_type)>*>
+        (data);
+      return (*f)(args);
+    }
+  else
+    {
+      std::size_t argc = args.Length();
+      std::vector<v8::Local<v8::Value> > argv (argc ? argc : 1 );
+      for(int i = 0; i != args.Length(); ++i)
+        argv[i] = args[i];
+      args.Callee()->NewInstance(argc, &argv[0]);
+      return eina::js::compatibility_return();
+    }
+}
+      
+template <typename...F>
+struct constructor_caller
+{
+  struct call
+  {
+    template <typename T>
+    void operator()(T function) const
+    {
+      int const parameters
+        = std::tuple_size<typename eina::_mpl::function_params<T>::type>::value;
+      if(*current + parameters <= args->Length())
+        {
+          aux(function, eina::make_index_sequence<parameters>());
+          *current += parameters;
+        }
+      else
+        {
+          eina::js::compatibility_throw
+            (v8::Exception::TypeError
+             (eina::js::compatibility_new<v8::String>(args->GetIsolate(), "Expected more arguments for this call")));
+          throw std::logic_error("");
+        }
+    }
+
+    template <typename U, std::size_t I>
+    static
+    typename std::tuple_element<I, typename eina::_mpl::function_params<U>::type>::type
+    get_value(v8::Local<v8::Value> v, v8::Isolate* isolate)
+    {
+      typename std::tuple_element<I, typename eina::_mpl::function_params<U>::type>::type
+        tmp = 
+        eina::js::get_value_from_javascript
+        (v, isolate, ""
+         , eina::js::value_tag<typename std::tuple_element
+         <I, typename eina::_mpl::function_params<U>::type>::type>());
+      return tmp;
+    }
+    
+    template <typename T, std::size_t... I>
+    void aux(T function, eina::index_sequence<I...>) const
+    {
+      function(get_value<T, I>((*args)[I + *current], args->GetIsolate())...);
+    }
+
+    int* current;
+    eina::js::compatibility_callback_info_pointer args;
+  };
+
+  eina::js::compatibility_return_type operator()(eina::js::compatibility_callback_info_type args) const
+  {
+    int current_index = 1;
+    if(args.Length() != 0)
+      {
+        try
+          {
+            Eo* parent = eina::js::get_value_from_javascript
+              (args[0], args.GetIsolate(), "", eina::js::value_tag<Eo*>());
+            Eo* eo = eo_add
+              (klass
+               , parent
+               , eina::_mpl::for_each(constructors, call{&current_index, &args})
+               );
+            assert(eo != 0);
+            v8::Local<v8::Object> self = args.This();
+            self->SetInternalField(0, eina::js::compatibility_new<v8::External>(args.GetIsolate(), eo));
+            efl::eina::js::make_weak(args.GetIsolate(), self
+                                     , [eo]
+                                     {
+                                       eo_unref(eo);
+                                     });
+          }
+        catch(std::logic_error const&) {}
+      }
+    else
+      {
+        eina::js::compatibility_throw
+          (v8::Exception::TypeError
+           (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Expected at least one argument for this call")));
+      }
+    return eina::js::compatibility_return();
+  }
+  
+  Eo_Class const* klass;
+  std::tuple<F...> constructors;
+};
+
+template <typename... F>
+v8::Handle<v8::Value> constructor_data(v8::Isolate* isolate, Eo_Class const* klass, F... f)
+{
+  return eina::js::compatibility_new<v8::External>
+    (isolate
+     , new std::function<eina::js::compatibility_return_type(eina::js::compatibility_callback_info_type)>
+     (constructor_caller<F...>{klass, std::tuple<F...>{f...}}));
+}
+
+} } }
+
+#endif
diff --git a/src/bindings/js/eo_js/eo_js_direction.hh b/src/bindings/js/eo_js/eo_js_direction.hh
new file mode 100644 (file)
index 0000000..96cd076
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef EFL_EO_JS_EO_JS_DIRECTION_HH
+#define EFL_EO_JS_EO_JS_DIRECTION_HH
+
+namespace efl { namespace eo { namespace js {
+
+struct input {};
+struct output {};
+struct input_output {};
+
+} } }
+
+#endif
diff --git a/src/bindings/js/eo_js/eo_js_event.hh b/src/bindings/js/eo_js/eo_js_event.hh
new file mode 100644 (file)
index 0000000..ab2dd34
--- /dev/null
@@ -0,0 +1,126 @@
+#ifndef EFL_EO_JS_EVENT_HH
+#define EFL_EO_JS_EVENT_HH
+
+#include <eina_tuple.hh>
+#include <eina_tuple_c.hh>
+#include <eina_function.hh>
+#include <Eo.h>
+
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <cassert>
+#include <vector>
+
+namespace efl { namespace eo { namespace js {
+
+struct event_information
+{
+  eina::js::global_ref<v8::Function>* constructor;
+  Eo_Event_Description const* event;
+  Eo_Event_Cb event_callback;
+  const char* class_name;
+};
+
+typedef std::map<std::string, event_information*> event_information_map;
+
+struct event_callback_information
+{
+  event_information* event_info;
+  eina::js::global_ref<v8::Function> function;
+};
+
+template <typename T>
+v8::Local<v8::Value> get_event_info(void* event_info, v8::Isolate* isolate, const char* class_name)
+{
+  using no_tag_type = typename eina::js::remove_tag<T>::type;
+  return eina::js::get_value_from_c(
+    eina::js::wrap_value<T>(*static_cast<no_tag_type*>(event_info), eina::js::value_tag<T>{}),
+    isolate,
+    class_name);
+}
+
+// FIXME: This shouldn't be necessary. Reveiew Eolian standards.
+template <>
+inline v8::Local<v8::Value> get_event_info<const char*>(void* event_info, v8::Isolate* isolate, const char*)
+{
+  return eina::js::get_value_from_c(static_cast<const char*>(event_info), isolate, "");
+}
+
+template <>
+inline v8::Local<v8::Value> get_event_info<void>(void*, v8::Isolate* isolate, const char*)
+{
+  return v8::Undefined(isolate);
+}
+
+template <typename T>
+inline Eina_Bool event_callback(void* data, Eo* obj, Eo_Event_Description const*
+                                , void* event_info)
+{
+  v8::Isolate* isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope handle_scope(isolate);
+  event_callback_information* event = static_cast<event_callback_information*>(data);
+  v8::Handle<v8::Value> a[] = {eina::js::compatibility_new<v8::External>(isolate, obj)};
+  v8::Local<v8::Object> self = (event->event_info->constructor->handle())->NewInstance(1, a);
+
+  v8::Local<v8::Value> call_args[] = {
+    self,
+    get_event_info<T>(event_info, isolate, event->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<v8::Value> ev_name = args[0];
+      v8::Local<v8::Value> f = args[1];
+      if (ev_name->IsString() && f->IsFunction())
+        {
+          v8::Local<v8::Value> data = args.Data();
+          auto ev_map =
+            static_cast<event_information_map*>
+            (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<v8::Object> self = args.This();
+          v8::Local<v8::Value> external = self->GetInternalField(0);
+          Eo* eo = static_cast<Eo*>(v8::External::Cast(*external)->Value());
+
+          auto isolate = args.GetIsolate();
+
+          event_callback_information* i = new event_callback_information
+            {event, {isolate, eina::js::compatibility_cast<v8::Function>(f)}};
+          eo_do(eo, eo_event_callback_priority_add
+                (event->event, EO_CALLBACK_PRIORITY_DEFAULT, event->event_callback, i));
+        }
+      else
+        {
+           eina::js::compatibility_throw
+             (v8::Exception::TypeError
+               (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Invalid argument type")));
+           throw std::logic_error("");
+        }
+    }
+  else
+    {
+       eina::js::compatibility_throw
+         (v8::Exception::TypeError
+           (eina::js::compatibility_new<v8::String>(args.GetIsolate(), "Expected more arguments for this call")));
+       throw std::logic_error("");
+    }
+  return eina::js::compatibility_return();
+}
+
+} } }
+
+#endif
diff --git a/src/bindings/js/eo_js/eo_js_namespace.hh b/src/bindings/js/eo_js/eo_js_namespace.hh
new file mode 100644 (file)
index 0000000..4fe9d9b
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef EFL_EO_JS_NAMESPACE_HH
+#define EFL_EO_JS_NAMESPACE_HH
+
+namespace efl { namespace eo { namespace js {
+
+inline
+v8::Local<v8::Object> get_namespace(std::vector<const char*> const& nss, v8::Isolate* isolate, v8::Local<v8::Object> to_export)
+{
+   for (auto ns : nss)
+     {
+        v8::Local<v8::Value> ns_obj = to_export->Get(::efl::eina::js::compatibility_new<v8::String>(isolate, ns));
+        if (ns_obj->IsUndefined() || ns_obj->IsNull())
+          {
+            ns_obj = ::efl::eina::js::compatibility_new<v8::Object>(isolate);
+            to_export->Set(::efl::eina::js::compatibility_new<v8::String>(isolate, ns), ns_obj);
+          }
+        to_export = ns_obj->ToObject();
+     }
+   return to_export;
+}
+
+} } }
+
+#endif
diff --git a/src/bindings/js/eo_js/eo_js_struct.hh b/src/bindings/js/eo_js/eo_js_struct.hh
new file mode 100644 (file)
index 0000000..731f9d0
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef EFL_EO_JS_STRUCT_HH
+#define EFL_EO_JS_STRUCT_HH
+
+#include <eina_tuple.hh>
+#include <eina_tuple_c.hh>
+#include <eina_function.hh>
+#include <Eo.h>
+
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <cassert>
+#include <vector>
+
+namespace efl { namespace eo { namespace js {
+
+template <typename S, typename M, M S::*MPtr, typename K>
+eina::js::compatibility_accessor_getter_return_type
+get_struct_member(v8::Local<v8::String>, eina::js::compatibility_accessor_getter_callback_info_type info)
+{
+  v8::Local<v8::Object> self_obj = eina::js::compatibility_cast<v8::Object>(info.This());
+  auto sct = static_cast<S*>(eina::js::compatibility_get_pointer_internal_field(self_obj, 0));
+  return eina::js::compatibility_return(eina::js::get_value_from_c(sct->*MPtr, info.GetIsolate(), K::class_name()), info);
+}
+
+template <typename S, typename GenTag, typename M, M S::*MPtr, typename K>
+eina::js::compatibility_accessor_setter_return_type
+set_struct_member(v8::Local<v8::String>, v8::Local<v8::Value> value, eina::js::compatibility_accessor_setter_callback_info_type info)
+{
+  v8::Local<v8::Object> self_obj = eina::js::compatibility_cast<v8::Object>(info.This());
+  auto sct = static_cast<S*>(eina::js::compatibility_get_pointer_internal_field(self_obj, 0));
+  sct->*MPtr = eina::js::get_value_from_javascript(value, info.GetIsolate(), K::class_name(), eina::js::value_tag<GenTag>());
+}
+
+template <typename S>
+eina::js::compatibility_return_type new_struct(eina::js::compatibility_callback_info_type args)
+{
+  if (!args.IsConstructCall())
+    return eina::js::compatibility_throw
+       (nullptr, v8::Exception::TypeError
+         (eina::js::compatibility_new<v8::String>(nullptr, "Not constructor call")));
+
+  if(args.Length() == 0)
+    {
+      S* p = new S{};
+      eina::js::compatibility_set_pointer_internal_field(args.This(), 0, static_cast<void*>(p));
+    }
+  else
+    {
+      if (!args[0]->IsExternal())
+        return eina::js::compatibility_throw
+           (nullptr, v8::Exception::TypeError
+             (eina::js::compatibility_new<v8::String>(nullptr, "Invalid argument type for constructor call")));
+
+      S* p = reinterpret_cast<S*>(v8::External::Cast(*args[0])->Value());
+      eina::js::compatibility_set_pointer_internal_field(args.This(), 0, static_cast<void*>(p));
+    }
+
+  return eina::js::compatibility_return();
+}
+
+template <typename S, typename F>
+inline void register_struct_persistent(v8::Isolate* isolate, const char* name, const char* full_name, F&& fields_func)
+{
+  v8::Handle<v8::FunctionTemplate> constructor = eina::js::compatibility_new<v8::FunctionTemplate>(isolate, &efl::eo::js::new_struct<S>);
+  constructor->SetClassName(eina::js::compatibility_new<v8::String>(isolate, name));
+
+  v8::Local<v8::ObjectTemplate> instance_t = constructor->InstanceTemplate();
+  instance_t->SetInternalFieldCount(1);
+  v8::Local<v8::ObjectTemplate> prototype = constructor->PrototypeTemplate();
+
+  fields_func(isolate, prototype);
+
+  static efl::eina::js::global_ref<v8::ObjectTemplate> instance_persistent{isolate, instance_t};
+  static efl::eina::js::global_ref<v8::Function> instance_template{isolate, constructor->GetFunction()};
+  (void)instance_persistent;
+
+  eina::js::register_class_constructor(full_name, instance_template.handle());
+}
+
+template <typename S, typename F>
+void register_struct_exports(v8::Isolate* isolate, const char* name, v8::Handle<v8::Object> exports, F&& fields_func)
+{
+  v8::Handle<v8::FunctionTemplate> constructor = eina::js::compatibility_new<v8::FunctionTemplate>(isolate, &efl::eo::js::new_struct<S>);
+  constructor->SetClassName(eina::js::compatibility_new<v8::String>(isolate, name));
+
+  v8::Local<v8::ObjectTemplate> instance_t = constructor->InstanceTemplate();
+  instance_t->SetInternalFieldCount(1);
+  v8::Local<v8::ObjectTemplate> prototype = constructor->PrototypeTemplate();
+
+  fields_func(isolate, prototype);
+
+  exports->Set(eina::js::compatibility_new<v8::String>(isolate, name), constructor->GetFunction());
+}
+
+
+template <typename S, typename F>
+void register_struct(v8::Isolate* isolate, const char* name, const char* full_name, v8::Handle<v8::Object> exports, F&& fields_func)
+{
+  register_struct_persistent<S>(isolate, name, full_name, std::forward<F>(fields_func));
+  register_struct_exports<S>(isolate, name, exports, std::forward<F>(fields_func));
+}
+
+} } }
+
+#endif
diff --git a/src/bindings/js/ethumb_js/Ethumb_Js.hh b/src/bindings/js/ethumb_js/Ethumb_Js.hh
new file mode 100644 (file)
index 0000000..3945970
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef ETHUMB_JS_INIT_HH
+#define ETHUMB_JS_INIT_HH
+
+#include <Eina.hh>
+
+#include <Eina_Js.hh>
+#include <Ethumb_Client.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ETHUMB_JS_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ETHUMB_JS_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+namespace efl { namespace ethumb { namespace js {
+
+using ::efl::eina::js::compatibility_new;
+using ::efl::eina::js::compatibility_return_type;
+using ::efl::eina::js::compatibility_callback_info_type;
+using ::efl::eina::js::compatibility_return;
+using ::efl::eina::js::compatibility_get_pointer_internal_field;
+using ::efl::eina::js::compatibility_set_pointer_internal_field;
+
+EAPI void register_ethumb(v8::Isolate *isolate, v8::Handle<v8::Object> exports);
+      
+} } } // namespace efl { namespace ethumb { namespace js {
+
+#endif /* ETHUMB_JS_INIT_HH */
diff --git a/src/bindings/js/ethumb_js/ethumb_js_client.cc b/src/bindings/js/ethumb_js/ethumb_js_client.cc
new file mode 100644 (file)
index 0000000..50aaee3
--- /dev/null
@@ -0,0 +1,571 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Ethumb_Js.hh>
+
+namespace efl { namespace ethumb { namespace js {
+
+namespace {
+
+Ethumb_Exists* extract_ethumb_exists(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field<Ethumb_Exists*>(object, 0);
+}
+
+efl::eina::js::global_ref<v8::Value>*
+extract_ethumb_exists_cb(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field
+        <efl::eina::js::global_ref<v8::Value>*>(object, 1);
+}
+
+v8::Local<v8::Object> wrap_ethumb_exists(Ethumb_Exists *exists,
+                                         efl::eina::js::global_ref<v8::Value>*
+                                         cb,
+                                         v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::Boolean;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(2);
+    auto ret = obj_tpl->NewInstance();
+
+    auto cancel = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto exists = extract_ethumb_exists(info.This());
+        auto cb = extract_ethumb_exists_cb(info.This());
+
+        if (ethumb_client_thumb_exists_check(exists))
+            return compatibility_return();
+
+        delete cb;
+
+        ethumb_client_thumb_exists_cancel(exists);
+        return compatibility_return();
+    };
+
+    auto check = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+        auto exists = extract_ethumb_exists(info.This());
+
+        auto ret = ethumb_client_thumb_exists_check(exists);
+
+        return compatibility_return(compatibility_new<Boolean>(isolate, ret),
+                                    info);
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "cancel"),
+             compatibility_new<FunctionTemplate>(isolate, cancel)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "check"),
+             compatibility_new<FunctionTemplate>(isolate, check)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, exists);
+    compatibility_set_pointer_internal_field(ret, 1, cb);
+
+    return ret;
+}
+
+// ====================================================
+
+Ethumb_Client_Async* extract_ethumb_client_async(v8::Local<v8::Object> o)
+{
+    return compatibility_get_pointer_internal_field<Ethumb_Client_Async*>(o, 0);
+}
+
+efl::eina::js::global_ref<v8::Value>*
+extract_ethumb_client_async_cb(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field
+        <efl::eina::js::global_ref<v8::Value>*>(object, 1);
+}
+
+Ethumb_Client* extract_ethumb_client_async_client(v8::Local<v8::Object> o)
+{
+    return compatibility_get_pointer_internal_field<Ethumb_Client*>(o, 0);
+}
+
+v8::Local<v8::Object>
+wrap_ethumb_client_async(Ethumb_Client_Async *request,
+                         efl::eina::js::global_ref<v8::Value>* cb,
+                         Ethumb_Client *client,
+                         v8::Isolate *isolate)
+{
+    using v8::String;
+    using v8::Boolean;
+    using v8::ObjectTemplate;
+    using v8::FunctionTemplate;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(3);
+    auto ret = obj_tpl->NewInstance();
+
+    auto cancel = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto request = extract_ethumb_client_async(info.This());
+        auto cb = extract_ethumb_client_async_cb(info.This());
+        auto client = extract_ethumb_client_async_client(info.This());
+
+        delete cb;
+
+        ethumb_client_thumb_async_cancel(client, request);
+        return compatibility_return();
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "cancel"),
+             compatibility_new<FunctionTemplate>(isolate, cancel)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, request);
+    compatibility_set_pointer_internal_field(ret, 1, cb);
+    compatibility_set_pointer_internal_field(ret, 2, client);
+
+    return ret;
+}
+
+Ethumb_Client* extract_ethumb_client(v8::Local<v8::Object> object)
+{
+    return compatibility_get_pointer_internal_field<Ethumb_Client*>(object, 0);
+}
+
+v8::Local<v8::Object> wrap_ethumb_client(Ethumb_Client *client,
+                                                v8::Isolate *isolate)
+{
+    using v8::Integer;
+    using v8::String;
+    using v8::Boolean;
+    using v8::Value;
+    using v8::Object;
+    using v8::ObjectTemplate;
+    using v8::Handle;
+    using v8::Function;
+    using v8::FunctionTemplate;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto obj_tpl = compatibility_new<ObjectTemplate>(isolate);
+    obj_tpl->SetInternalFieldCount(1);
+    auto ret = obj_tpl->NewInstance();
+
+    auto disconnect = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ethumb_client_disconnect(extract_ethumb_client(info.This()));
+        return compatibility_return();
+    };
+
+    auto on_server_die_callback_set = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 1 || !info[0]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+
+        unique_ptr<persistent_t> cb_data{new persistent_t(isolate, info[0])};
+
+        auto client = extract_ethumb_client(info.This());
+        auto server_die_cb = [](void *data, Ethumb_Client *client) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args{wrap_ethumb_client(client, isolate)};
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+        };
+        auto free_data = [](void *data) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            delete persistent;
+        };
+
+        ethumb_client_on_server_die_callback_set(client, server_die_cb,
+                                                 cb_data.release(), free_data);
+        return compatibility_return();
+    };
+
+    auto file_set = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 2 || !info[0]->IsString() || !info[1]->IsString())
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+
+        auto ret = ethumb_client_file_set(extract_ethumb_client(info.This()),
+                                          *String::Utf8Value(info[0]),
+                                          *String::Utf8Value(info[1]));
+        return compatibility_return(compatibility_new<Boolean>(isolate, ret),
+                                    info);
+    };
+
+    auto file_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+
+        auto ret = compatibility_new<Object>(isolate);
+        const char *path;
+        const char *key;
+
+        ethumb_client_file_get(extract_ethumb_client(info.This()), &path, &key);
+
+        ret->Set(compatibility_new<String>(isolate, "path"),
+                 compatibility_new<String>(isolate, path));
+        ret->Set(compatibility_new<String>(isolate, "key"),
+                 compatibility_new<String>(isolate, key));
+
+        return compatibility_return(ret, info);
+    };
+
+    auto file_free = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 0)
+            return compatibility_return();
+
+        ethumb_client_file_free(extract_ethumb_client(info.This()));
+
+        return compatibility_return();
+    };
+
+    auto thumb_exists = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 1 || !info[0]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+
+        unique_ptr<persistent_t> cb_data{new persistent_t(isolate, info[0])};
+
+        auto client = extract_ethumb_client(info.This());
+        auto exists_cb = [](void *data, Ethumb_Client *client,
+                            Ethumb_Exists *thread, Eina_Bool exists) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[3] = {
+                wrap_ethumb_client(client, isolate),
+                wrap_ethumb_exists(thread, NULL, isolate),
+                compatibility_new<Boolean>(isolate, exists)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 3, args);
+
+            delete persistent;
+        };
+
+        auto ret = ethumb_client_thumb_exists(client, exists_cb,
+                                              cb_data.get());
+        return compatibility_return(wrap_ethumb_exists(ret, cb_data.release(),
+                                                       isolate),
+                                    info);
+    };
+
+    auto generate = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 1 || !info[0]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+
+        unique_ptr<persistent_t> cb_data{new persistent_t(isolate, info[0])};
+
+        auto client = extract_ethumb_client(info.This());
+        auto generated_cb = [](void *data, Ethumb_Client *client, int id,
+                               const char *file, const char *key,
+                               const char *thumb_path, const char *thumb_key,
+                               Eina_Bool success) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[7] = {
+                wrap_ethumb_client(client, isolate),
+                compatibility_new<Integer>(isolate, id),
+                compatibility_new<String>(isolate, file),
+                compatibility_new<String>(isolate, key),
+                compatibility_new<String>(isolate, thumb_path),
+                compatibility_new<String>(isolate, thumb_key),
+                compatibility_new<Boolean>(isolate, success)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 7, args);
+        };
+        auto free_data = [](void *data) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            delete persistent;
+        };
+
+        auto ret = ethumb_client_generate(client, generated_cb,
+                                          cb_data.release(), free_data);
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    info);
+    };
+
+    auto generate_cancel = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 2 || !info[0]->IsNumber()
+            || !info[1]->IsFunction()) {
+            return compatibility_return();
+        }
+
+        auto isolate = info.GetIsolate();
+
+        unique_ptr<persistent_t> cb_data{new persistent_t(isolate, info[1])};
+
+        auto client = extract_ethumb_client(info.This());
+        auto cancel_cb = [](void *data, Eina_Bool success) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args{compatibility_new<Boolean>(isolate, success)};
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+        };
+        auto free_data = [](void *data) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            delete persistent;
+        };
+
+        ethumb_client_generate_cancel(client, info[0]->IntegerValue(),
+                                      cancel_cb, cb_data.release(), free_data);
+        return compatibility_return();
+    };
+
+    auto generate_cancel_all = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 1 || !info[0]->IsFunction())
+            return compatibility_return();
+
+        auto client = extract_ethumb_client(info.This());
+
+        ethumb_client_generate_cancel_all(client);
+        return compatibility_return();
+    };
+
+    auto thumb_async_get = [](compatibility_callback_info_type info)
+        -> compatibility_return_type {
+        if (info.Length() != 1 || !info[0]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = info.GetIsolate();
+
+        unique_ptr<persistent_t> cb_data{new persistent_t(isolate, info[0])};
+
+        auto client = extract_ethumb_client(info.This());
+        auto done_cb = [](Ethumb_Client *client, const char *thumb_path,
+                          const char *thumb_key, void *data) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[3] = {
+                wrap_ethumb_client(client, isolate),
+                compatibility_new<String>(isolate, thumb_path),
+                compatibility_new<String>(isolate, thumb_key)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 3, args);
+
+            delete persistent;
+        };
+        auto error_cb = [](Ethumb_Client *client, void *data) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args{wrap_ethumb_client(client, isolate)};
+
+            Function::Cast(*o)->Call(o->ToObject(), 1, &args);
+
+            delete persistent;
+        };
+
+        auto ret = ethumb_client_thumb_async_get(client, done_cb, error_cb,
+                                                 cb_data.get());
+        auto wrapped_ret = wrap_ethumb_client_async(ret, cb_data.release(),
+                                                    client, isolate);
+        return compatibility_return(wrapped_ret, info);
+    };
+
+    ret->Set(compatibility_new<String>(isolate, "disconnect"),
+             compatibility_new<FunctionTemplate>(isolate, disconnect)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "on_server_die_callback_set"),
+             compatibility_new<FunctionTemplate>(isolate,
+                                                 on_server_die_callback_set)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "file_set"),
+             compatibility_new<FunctionTemplate>(isolate, file_set)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "file_get"),
+             compatibility_new<FunctionTemplate>(isolate, file_get)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "file_free"),
+             compatibility_new<FunctionTemplate>(isolate, file_free)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "thumb_exists"),
+             compatibility_new<FunctionTemplate>(isolate, thumb_exists)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "generate"),
+             compatibility_new<FunctionTemplate>(isolate, generate)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "generate_cancel"),
+             compatibility_new<FunctionTemplate>(isolate, generate_cancel)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "generate_cancel_all"),
+             compatibility_new<FunctionTemplate>(isolate, generate_cancel_all)
+             ->GetFunction());
+    ret->Set(compatibility_new<String>(isolate, "thumb_async_get"),
+             compatibility_new<FunctionTemplate>(isolate, thumb_async_get)
+             ->GetFunction());
+
+    compatibility_set_pointer_internal_field(ret, 0, client);
+
+    return ret;
+}
+
+EAPI
+void register_client_init(v8::Isolate *isolate, v8::Handle<v8::Object> global,
+                          v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto init = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ethumb_client_init();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, init)
+                ->GetFunction());
+}
+
+EAPI
+void register_client_shutdown(v8::Isolate *isolate,
+                              v8::Handle<v8::Object> global,
+                              v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::FunctionTemplate;
+
+    auto shutdown = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 0)
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+        auto ret = ethumb_client_shutdown();
+        return compatibility_return(compatibility_new<Integer>(isolate, ret),
+                                    args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, shutdown)
+                ->GetFunction());
+}
+
+EAPI
+void register_client_connect(v8::Isolate *isolate,
+                             v8::Handle<v8::Object> global,
+                             v8::Handle<v8::String> name)
+{
+    using v8::Integer;
+    using v8::Boolean;
+    using v8::Value;
+    using v8::FunctionTemplate;
+    using v8::Function;
+    using v8::Handle;
+    using std::unique_ptr;
+
+    typedef efl::eina::js::global_ref<Value> persistent_t;
+
+    auto shutdown = [](compatibility_callback_info_type args)
+        -> compatibility_return_type {
+        if (args.Length() != 1 || !args[0]->IsFunction())
+            return compatibility_return();
+
+        auto isolate = args.GetIsolate();
+
+        unique_ptr<persistent_t> cb_data{new persistent_t(isolate, args[0])};
+
+        auto connect_cb = [](void *data, Ethumb_Client *client,
+                             Eina_Bool success) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            auto o = persistent->handle();
+
+            auto isolate = v8::Isolate::GetCurrent();
+
+            Handle<Value> args[2] = {
+                wrap_ethumb_client(client, isolate),
+                compatibility_new<Boolean>(isolate, success)
+            };
+
+            Function::Cast(*o)->Call(o->ToObject(), 2, args);
+        };
+        auto free_data = [](void *data) {
+            auto persistent = reinterpret_cast<persistent_t*>(data);
+            delete persistent;
+        };
+
+        auto ret = ethumb_client_connect(connect_cb, cb_data.release(),
+                                         free_data);
+        return compatibility_return(wrap_ethumb_client(ret, isolate), args);
+    };
+
+    global->Set(name,
+                compatibility_new<FunctionTemplate>(isolate, shutdown)
+                ->GetFunction());
+}
+
+}
+
+EAPI
+void register_ethumb(v8::Isolate *isolate, v8::Handle<v8::Object> exports)
+{
+   using v8::String;
+   register_client_init(isolate, exports,
+                        compatibility_new<String>(isolate,
+                                                  "ethumb_client_init"));
+   register_client_shutdown(isolate, exports,
+                            compatibility_new<String>(isolate,
+                                                      "ethumb_client_shutdown"));
+   register_client_connect(isolate, exports,
+                           compatibility_new<String>(isolate,
+                                                     "ethumb_client_connect"));
+}
+      
+} } } // namespace efl { namespace ethumb { namespace js {
index e5a4c4c..88d7c35 100644 (file)
@@ -909,7 +909,6 @@ _ecore_memory_statistic(EINA_UNUSED void *data)
 #endif
 #ifdef HAVE_MALLOC_INFO
    if (frame) fputs("\n", _ecore_memory_statistic_file);
-   fprintf(_ecore_memory_statistic_file, "=== Frame %i ===\n\n", frame++);
    malloc_info(0, _ecore_memory_statistic_file);
 #endif
 
index ebd66eb..f7e6a8a 100644 (file)
@@ -61,7 +61,7 @@
 #include "Ecore.h"
 #include "ecore_private.h"
 
-#ifdef HAVE_SYS_EPOLL_H
+#if defined(HAVE_SYS_EPOLL_H) && !defined(HAVE_LIBUV)
 # define HAVE_EPOLL   1
 # include <sys/epoll.h>
 #else
@@ -157,6 +157,51 @@ timerfd_settime(int                      fd EINA_UNUSED,
 # include <glib.h>
 #endif
 
+#ifdef HAVE_LIBUV
+#ifdef HAVE_NODE_UV_H
+#include <node/uv.h>
+#elif defined(HAVE_NODEJS_DEPS_UV_UV_H)
+#include <nodejs/deps/uv/uv.h>
+#elif defined(HAVE_NODEJS_DEPS_UV_INCLUDE_UV_H)
+#include <nodejs/deps/uv/include/uv.h>
+#elif defined(HAVE_NODEJS_SRC_UV_H)
+#include <nodejs/src/uv.h>
+#elif defined(HAVE_UV_H)
+#include <uv.h>
+#else
+#error No uv.h header found?
+#endif
+
+#include <dlfcn.h>
+
+static uv_prepare_t _ecore_main_uv_prepare;
+static uv_check_t _ecore_main_uv_check;
+static uv_timer_t _ecore_main_uv_handle_timers;
+static Eina_Bool _ecore_main_uv_idling;
+
+static int (*_dl_uv_loop_alive)(uv_loop_t*) = 0;
+static int (*_dl_uv_run)(uv_loop_t*, uv_run_mode mode) = 0;
+static int (*_dl_uv_stop)(uv_loop_t*) = 0;
+static uv_loop_t* (*_dl_uv_default_loop)() = 0;
+static int (*_dl_uv_poll_init_socket)(uv_loop_t* loop, uv_poll_t* handle, uv_os_sock_t fd) = 0;
+static int (*_dl_uv_poll_init)(uv_loop_t* loop, uv_poll_t* handle, int fd) = 0;
+static int (*_dl_uv_poll_start)(uv_poll_t* handle, int events, uv_poll_cb cb) = 0;
+static int (*_dl_uv_poll_stop)(uv_poll_t* handle) = 0;
+static int (*_dl_uv_timer_init)(uv_loop_t*, uv_timer_t* handle);
+static int (*_dl_uv_timer_start)(uv_timer_t* handle,
+                                 uv_timer_cb cb,
+                                 uint64_t timeout,
+                                 uint64_t repeat);
+static int (*_dl_uv_timer_stop)(uv_timer_t* handle);
+static int (*_dl_uv_prepare_init)(uv_loop_t*, uv_prepare_t* prepare);
+static int (*_dl_uv_prepare_start)(uv_prepare_t* prepare, uv_prepare_cb cb);
+static int (*_dl_uv_prepare_stop)(uv_prepare_t* prepare);
+static int (*_dl_uv_check_init)(uv_loop_t*, uv_check_t* prepare);
+static int (*_dl_uv_check_start)(uv_check_t* prepare, uv_check_cb cb);
+static int (*_dl_uv_check_stop)(uv_check_t* prepare);
+static int (*_dl_uv_close)(uv_handle_t* handle, uv_close_cb close_cb);
+#endif
+
 #define NS_PER_SEC (1000.0 * 1000.0 * 1000.0)
 
 struct _Ecore_Fd_Handler
@@ -181,6 +226,9 @@ struct _Ecore_Fd_Handler
 #if defined(USE_G_MAIN_LOOP)
    GPollFD                gfd;
 #endif
+#ifdef HAVE_LIBUV
+   uv_poll_t              uv_handle;
+#endif
 };
 GENERIC_ALLOC_SIZE_DECLARE(Ecore_Fd_Handler);
 
@@ -198,7 +246,7 @@ struct _Ecore_Win32_Handler
 GENERIC_ALLOC_SIZE_DECLARE(Ecore_Win32_Handler);
 #endif
 
-#ifndef USE_G_MAIN_LOOP
+#if !defined(USE_G_MAIN_LOOP) && !defined(HAVE_LIBUV)
 static int  _ecore_main_select(double timeout);
 #endif
 static void _ecore_main_prepare_handlers(void);
@@ -310,9 +358,13 @@ _ecore_try_add_to_call_list(Ecore_Fd_Handler *fdh)
 {
    /* check if this fdh is already in the list */
    if (fdh->next_ready)
-     return;
+     {
+       DBG("next_ready");
+       return;
+     }
    if (fdh->read_active || fdh->write_active || fdh->error_active)
      {
+       DBG("added");
         /*
          * make sure next_ready is non-null by pointing to ourselves
          * use that to indicate this fdh is in the ready list
@@ -344,6 +396,7 @@ _ecore_epoll_add(int   efd,
                  int   events,
                  void *ptr)
 {
+   
    struct epoll_event ev;
 
    memset(&ev, 0, sizeof (ev));
@@ -375,97 +428,197 @@ _gfd_events_from_fdh(Ecore_Fd_Handler *fdh)
 }
 #endif
 
+#ifdef HAVE_LIBUV
+static void
+_ecore_main_uv_poll_cb(uv_poll_t* handle, int status, int events)
+{
+   DBG("_ecore_main_uv_poll_cb %p status %d events %d", (void*)handle->data, status, events);
+   Ecore_Fd_Handler* fdh = handle->data;
+
+   if(_ecore_main_uv_idling)
+     {
+       DBG("not IDLE anymore");
+       _ecore_main_uv_idling = EINA_FALSE;
+       _ecore_idle_exiter_call();
+       _ecore_animator_run_reset();
+     }
+  
+  if (status)
+    fdh->error_active = EINA_TRUE;
+  if (events & UV_READABLE)
+    fdh->read_active = EINA_TRUE;
+  if (events & UV_WRITABLE)
+    fdh->write_active = EINA_TRUE;
+
+  _ecore_try_add_to_call_list(fdh);
+
+  _ecore_main_fd_handlers_call();
+  if (fd_handlers_with_buffer)
+    _ecore_main_fd_handlers_buf_call();
+  _ecore_signal_received_process();
+  _ecore_event_call();
+  _ecore_main_fd_handlers_cleanup();
+  _ecore_timer_expired_timers_call(_ecore_time_loop_time);
+  _ecore_timer_cleanup();
+}
+
+static int
+_ecore_main_uv_events_from_fdh(Ecore_Fd_Handler *fdh)
+{
+   int events = 0;
+   if (fdh->flags & ECORE_FD_READ) events |= UV_READABLE;
+   if (fdh->flags & ECORE_FD_WRITE) events |= UV_WRITABLE;
+   DBG("events is %d", (int)events);
+   return events;
+}
+#endif
+
 static inline int
 _ecore_main_fdh_poll_add(Ecore_Fd_Handler *fdh)
 {
+   DBG("_ecore_main_fdh_poll_add");
    int r = 0;
 
-   if ((!fdh->file) && HAVE_EPOLL && epoll_fd >= 0)
+#ifdef HAVE_LIBUV
+   if(!_dl_uv_run)
+#endif
      {
-        r = _ecore_epoll_add(_ecore_get_epoll_fd(), fdh->fd,
-                             _ecore_poll_events_from_fdh(fdh), fdh);
+       if ((!fdh->file) && HAVE_EPOLL && epoll_fd >= 0)
+         {
+           r = _ecore_epoll_add(_ecore_get_epoll_fd(), fdh->fd,
+                                _ecore_poll_events_from_fdh(fdh), fdh);
+         }
      }
-#ifdef USE_G_MAIN_LOOP
+#ifdef HAVE_LIBUV
    else
+#endif
      {
+#ifdef HAVE_LIBUV
+       if(!fdh->file)
+         {
+           DBG("_ecore_main_fdh_poll_add libuv socket %p", fdh);
+           fdh->uv_handle.data = fdh;
+           DBG("_ecore_main_fdh_poll_add2 %p", fdh);
+           _dl_uv_poll_init_socket(_dl_uv_default_loop(), &fdh->uv_handle, fdh->fd);
+           DBG("_ecore_main_fdh_poll_add3 %p", fdh->uv_handle.data);
+           _dl_uv_poll_start(&fdh->uv_handle, _ecore_main_uv_events_from_fdh(fdh)
+                             , _ecore_main_uv_poll_cb);
+           DBG("_ecore_main_fdh_poll_add libuv DONE");
+         }
+       else
+         {
+           DBG("_ecore_main_fdh_poll_add libuv file");
+           fdh->uv_handle.data = fdh;
+           DBG("_ecore_main_fdh_poll_add2 %p", fdh);
+           _dl_uv_poll_init(_dl_uv_default_loop(), &fdh->uv_handle, fdh->fd);
+           DBG("_ecore_main_fdh_poll_add3 %p", fdh->uv_handle.data);
+           _dl_uv_poll_start(&fdh->uv_handle, _ecore_main_uv_events_from_fdh(fdh)
+                             , _ecore_main_uv_poll_cb);
+           DBG("_ecore_main_fdh_poll_add libuv DONE");
+         }
+#elif defined(USE_G_MAIN_LOOP)
         fdh->gfd.fd = fdh->fd;
         fdh->gfd.events = _gfd_events_from_fdh(fdh);
         fdh->gfd.revents = 0;
         DBG("adding gpoll on %d %08x", fdh->fd, fdh->gfd.events);
         g_source_add_poll(ecore_glib_source, &fdh->gfd);
-     }
 #endif
+     }
    return r;
 }
 
 static inline void
 _ecore_main_fdh_poll_del(Ecore_Fd_Handler *fdh)
 {
-   if ((!fdh->file) && HAVE_EPOLL && epoll_fd >= 0)
+#ifdef HAVE_LIBUV
+   if(!_dl_uv_run)
+#endif
      {
-        struct epoll_event ev;
-        int efd = _ecore_get_epoll_fd();
-
-        memset(&ev, 0, sizeof (ev));
-        DBG("removing poll on %d", fdh->fd);
-        /* could get an EBADF if somebody closed the FD before removing it */
-        if ((epoll_ctl(efd, EPOLL_CTL_DEL, fdh->fd, &ev) < 0))
-          {
-             if (errno == EBADF)
-               {
-                  WRN("fd %d was closed, can't remove from epoll - reinit!",
-                      fdh->fd);
-                  _ecore_main_loop_shutdown();
-                  _ecore_main_loop_init();
-               }
-             else
-               {
-                  ERR("Failed to delete epoll fd %d! (errno=%d)", fdh->fd, errno);
-               }
-          }
-     }
-#ifdef USE_G_MAIN_LOOP
+       if ((!fdh->file) && HAVE_EPOLL && epoll_fd >= 0)
+         {
+           struct epoll_event ev;
+           int efd = _ecore_get_epoll_fd();
+
+           memset(&ev, 0, sizeof (ev));
+           DBG("removing poll on %d", fdh->fd);
+           /* could get an EBADF if somebody closed the FD before removing it */
+           if ((epoll_ctl(efd, EPOLL_CTL_DEL, fdh->fd, &ev) < 0))
+             {
+               if (errno == EBADF)
+                 {
+                   WRN("fd %d was closed, can't remove from epoll - reinit!",
+                       fdh->fd);
+                   _ecore_main_loop_shutdown();
+                   _ecore_main_loop_init();
+                 }
+               else
+                 {
+                   ERR("Failed to delete epoll fd %d! (errno=%d)", fdh->fd, errno);
+                 }
+             }
+         }
+     }
+#ifdef HAVE_LIBUV
    else
+#endif
      {
+#ifdef HAVE_LIBUV
+       DBG("_ecore_main_fdh_poll_del libuv %p", fdh);
+       uv_handle_t* h = (uv_handle_t*)&fdh->uv_handle;
+       _dl_uv_close(h, 0);
+       DBG("_ecore_main_fdh_poll_del libuv DONE");
+#elif USE_G_MAIN_LOOP
         fdh->gfd.fd = fdh->fd;
         fdh->gfd.events = _gfd_events_from_fdh(fdh);
         fdh->gfd.revents = 0;
         DBG("removing gpoll on %d %08x", fdh->fd, fdh->gfd.events);
         g_source_remove_poll(ecore_glib_source, &fdh->gfd);
-     }
 #endif
+     }
 }
 
 static inline int
 _ecore_main_fdh_poll_modify(Ecore_Fd_Handler *fdh)
 {
+   DBG("_ecore_main_fdh_poll_modify %p", fdh);
    int r = 0;
-   if ((!fdh->file) && HAVE_EPOLL && epoll_fd >= 0)
+#ifdef HAVE_LIBUV
+   if(!_dl_uv_run)
+#endif
      {
-        struct epoll_event ev;
-        int efd = _ecore_get_epoll_fd();
+       if ((!fdh->file) && HAVE_EPOLL && epoll_fd >= 0)
+         {
+           struct epoll_event ev;
+           int efd = _ecore_get_epoll_fd();
 
-        memset(&ev, 0, sizeof (ev));
-        ev.events = _ecore_poll_events_from_fdh(fdh);
-        ev.data.ptr = fdh;
-        DBG("modifing epoll on %d to %08x", fdh->fd, ev.events);
-        r = epoll_ctl(efd, EPOLL_CTL_MOD, fdh->fd, &ev);
+           memset(&ev, 0, sizeof (ev));
+           ev.events = _ecore_poll_events_from_fdh(fdh);
+           ev.data.ptr = fdh;
+           DBG("modifing epoll on %d to %08x", fdh->fd, ev.events);
+           r = epoll_ctl(efd, EPOLL_CTL_MOD, fdh->fd, &ev);
+         }
      }
-#ifdef USE_G_MAIN_LOOP
+#ifdef HAVE_LIBUV
    else
+#endif
      {
+#ifdef HAVE_LIBUV
+       _dl_uv_poll_start(&fdh->uv_handle, _ecore_main_uv_events_from_fdh(fdh)
+                         , _ecore_main_uv_poll_cb);
+#elif defined(USE_G_MAIN_LOOP)
         fdh->gfd.fd = fdh->fd;
         fdh->gfd.events = _gfd_events_from_fdh(fdh);
         fdh->gfd.revents = 0;
         DBG("modifing gpoll on %d to %08x", fdh->fd, fdh->gfd.events);
-     }
 #endif
+     }
    return r;
 }
 
 static inline int
 _ecore_main_fdh_epoll_mark_active(void)
 {
+   DBG("_ecore_main_fdh_epoll_mark_active");
    struct epoll_event ev[32];
    int i, ret;
    int efd = _ecore_get_epoll_fd();
@@ -832,9 +985,62 @@ detect_time_changes_stop(void)
 #endif
 }
 
+
+#ifdef HAVE_LIBUV
+static inline
+void
+_ecore_main_loop_uv_check(uv_check_t* handle EINA_UNUSED);
+static void _ecore_main_loop_uv_prepare(uv_prepare_t* handle);
+
+static
+void _ecore_main_loop_timer_run(uv_timer_t* timer EINA_UNUSED)
+{
+  if(_ecore_main_uv_idling)
+    {
+      _ecore_main_uv_idling = EINA_FALSE;
+      _ecore_idle_exiter_call();
+      _ecore_animator_run_reset();
+    }
+  _ecore_time_loop_time = ecore_time_get();
+  _ecore_main_loop_uv_check(NULL);
+  
+  _ecore_main_loop_uv_prepare(NULL);
+}
+static void _ecore_main_loop_uv_prepare(uv_prepare_t* handle);
+
+static inline
+void
+_ecore_main_loop_uv_check(uv_check_t* handle EINA_UNUSED)
+{
+   DBG("_ecore_main_loop_uv_check idling? %d", (int)_ecore_main_uv_idling);
+   in_main_loop++;
+   _ecore_lock();
+
+   if(do_quit)
+     goto quit;
+   
+   do
+     {
+       _ecore_main_fd_handlers_call();
+       if (fd_handlers_with_buffer)
+         _ecore_main_fd_handlers_buf_call();
+       _ecore_signal_received_process();
+       _ecore_event_call();
+       _ecore_main_fd_handlers_cleanup();
+       _ecore_timer_expired_timers_call(_ecore_time_loop_time);
+       _ecore_timer_cleanup();
+     }
+   while(fd_handlers_to_call);
+quit:   
+   in_main_loop--;
+   _ecore_unlock();
+}
+#endif
+
 void
 _ecore_main_loop_init(void)
 {
+   DBG("_ecore_main_loop_init");
    epoll_fd = epoll_create(1);
    if ((epoll_fd < 0) && HAVE_EPOLL)
      WRN("Failed to create epoll fd!");
@@ -851,7 +1057,77 @@ _ecore_main_loop_init(void)
                          _ecore_poll_events_from_fdh(fdh), fdh);
         _ecore_main_fdh_poll_add(fdh);
      }
+#ifdef HAVE_LIBUV
+   {
+     DBG("loading lib uv");
+#ifdef HAVE_NODEJS
+     void* lib = dlopen(NULL, RTLD_LAZY);
+#else
+     void* lib = dlopen("libuv.so", RTLD_GLOBAL | RTLD_LAZY);
+#endif
 
+     if(lib && dlsym(lib, "uv_run"))
+       {
+         DBG("loaded lib uv");
+         _dl_uv_run = dlsym(lib, "uv_run");
+         assert(!!_dl_uv_run);
+         _dl_uv_stop = dlsym(lib, "uv_stop");
+         assert(!!_dl_uv_stop);
+         _dl_uv_default_loop = dlsym(lib, "uv_default_loop");
+         assert(!!_dl_uv_default_loop);
+         _dl_uv_poll_init_socket = dlsym(lib, "uv_poll_init_socket");
+         assert(!!_dl_uv_poll_init_socket);
+         _dl_uv_poll_init = dlsym(lib, "uv_poll_init");
+         assert(!!_dl_uv_poll_init);
+         _dl_uv_poll_start = dlsym(lib, "uv_poll_start");
+         assert(!!_dl_uv_poll_start);
+         _dl_uv_poll_stop = dlsym(lib, "uv_poll_stop");
+         assert(!!_dl_uv_poll_stop);
+         _dl_uv_timer_init = dlsym(lib, "uv_timer_init");
+         assert(!!_dl_uv_timer_init);
+         _dl_uv_timer_start = dlsym(lib, "uv_timer_start");
+         assert(!!_dl_uv_timer_start);
+         _dl_uv_timer_stop = dlsym(lib, "uv_timer_stop");
+         assert(!!_dl_uv_timer_stop);
+         _dl_uv_prepare_init = dlsym(lib, "uv_prepare_init");
+         assert(!!_dl_uv_prepare_init);
+         _dl_uv_prepare_start = dlsym(lib, "uv_prepare_start");
+         assert(!!_dl_uv_prepare_start);
+         _dl_uv_prepare_stop = dlsym(lib, "uv_prepare_stop");
+         assert(!!_dl_uv_prepare_stop);
+         _dl_uv_check_init = dlsym(lib, "uv_check_init");
+         assert(!!_dl_uv_check_init);
+         _dl_uv_check_start = dlsym(lib, "uv_check_start");
+         assert(!!_dl_uv_check_start);
+         _dl_uv_check_stop = dlsym(lib, "uv_check_stop");
+         assert(!!_dl_uv_check_stop);
+         _dl_uv_close = dlsym(lib, "uv_close");
+         assert(!!_dl_uv_close);
+         _dl_uv_loop_alive = dlsym(lib, "uv_loop_alive");
+         assert(!!_dl_uv_loop_alive);
+
+  //dlclose(lib);
+
+         DBG("_dl_uv_prepare_init");
+         _dl_uv_prepare_init(_dl_uv_default_loop(), &_ecore_main_uv_prepare);
+         DBG("_dl_uv_prepare_start");
+         _dl_uv_prepare_start(&_ecore_main_uv_prepare, &_ecore_main_loop_uv_prepare);
+         DBG("_dl_uv_prepare_started");
+
+         DBG("_dl_uv_check_init");
+         _dl_uv_check_init(_dl_uv_default_loop(), &_ecore_main_uv_check);
+         DBG("_dl_uv_check_start");
+         _dl_uv_check_start(&_ecore_main_uv_check, &_ecore_main_loop_uv_check);
+         DBG("_dl_uv_check_started");
+
+         _dl_uv_timer_init(_dl_uv_default_loop(),  &_ecore_main_uv_handle_timers);
+       }
+     /* else */
+     /*   DBG("did not load uv"); */
+     DBG("loaded dlsyms uv");
+   }
+#endif
+   
    /* setup for the g_main_loop only integration */
 #ifdef USE_G_MAIN_LOOP
    ecore_glib_source = g_source_new(&ecore_gsource_funcs, sizeof (GSource));
@@ -916,11 +1192,21 @@ _ecore_main_loop_shutdown(void)
         close(timer_fd);
         timer_fd = -1;
      }
+
+#ifdef HAVE_LIBUV
+   if(_dl_uv_run)
+     {
+       DBG("_ecore_main_loop_shutdown");
+       _dl_uv_timer_stop(&_ecore_main_uv_handle_timers);
+       _dl_uv_close((uv_handle_t*)&_ecore_main_uv_handle_timers, 0);
+     }
+#endif
 }
 
 void *
 _ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
 {
+   DBG("_ecore_main_fd_handler_del %p", fd_handler);
    if (fd_handler->delete_me)
      {
         ERR("fdh %p deleted twice", fd_handler);
@@ -941,6 +1227,9 @@ EAPI void
 ecore_main_loop_iterate(void)
 {
    EINA_MAIN_LOOP_CHECK_RETURN;
+#ifdef HAVE_LIBUV
+   if(!_dl_uv_run) {
+#endif
 #ifndef USE_G_MAIN_LOOP
    _ecore_lock();
    _ecore_time_loop_time = ecore_time_get();
@@ -949,12 +1238,20 @@ ecore_main_loop_iterate(void)
 #else
    g_main_context_iteration(NULL, 0);
 #endif
+#ifdef HAVE_LIBUV
+   }
+   else
+     _dl_uv_run(_dl_uv_default_loop(), UV_RUN_ONCE | UV_RUN_NOWAIT);
+#endif
 }
 
 EAPI int
 ecore_main_loop_iterate_may_block(int may_block)
 {
    EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
+#ifdef HAVE_LIBUV
+   if(!_dl_uv_run) {
+#endif
 #ifndef USE_G_MAIN_LOOP
    _ecore_lock();
    _ecore_time_loop_time = ecore_time_get();
@@ -966,11 +1263,18 @@ in_main_loop--;
 #else
    return g_main_context_iteration(NULL, may_block);
 #endif
+#ifdef HAVE_LIBUV
+   }
+   else
+     _dl_uv_run(_dl_uv_default_loop(), may_block ? UV_RUN_ONCE | UV_RUN_NOWAIT : UV_RUN_ONCE);
+#endif
+   return 0;
 }
 
 EAPI void
 ecore_main_loop_begin(void)
 {
+   DBG("ecore_main_loop_begin");
    EINA_MAIN_LOOP_CHECK_RETURN;
    if (in_main_loop > 0)
      {
@@ -981,6 +1285,9 @@ ecore_main_loop_begin(void)
 #ifdef HAVE_SYSTEMD
    sd_notify(0, "READY=1");
 #endif
+#ifdef HAVE_LIBUV
+   if(!_dl_uv_run) {
+#endif
 #ifndef USE_G_MAIN_LOOP
    _ecore_lock();
    in_main_loop++;
@@ -998,6 +1305,20 @@ ecore_main_loop_begin(void)
      }
    do_quit = 0;
 #endif
+#ifdef HAVE_LIBUV
+   }
+   else
+     {
+       DBG("uv_run");
+       _ecore_time_loop_time = ecore_time_get();
+       in_main_loop++;
+       while(!do_quit)
+         _dl_uv_run(_dl_uv_default_loop(), UV_RUN_DEFAULT);
+       in_main_loop--;
+       do_quit = 0;
+       DBG("quit");
+     }
+#endif
    eina_evlog("-mainloop", NULL, 0.0, NULL);
 }
 
@@ -1009,6 +1330,9 @@ ecore_main_loop_quit(void)
 #ifdef USE_G_MAIN_LOOP
    if (ecore_main_loop)
      g_main_loop_quit(ecore_main_loop);
+#elif defined(HAVE_LIBUV)
+   if (_dl_uv_run)
+     _dl_uv_stop(_dl_uv_default_loop());
 #endif
 }
 
@@ -1021,6 +1345,7 @@ ecore_main_loop_nested_get(void)
 EAPI Eina_Bool
 ecore_main_loop_animator_ticked_get(void)
 {
+   DBG("ecore_main_loop_animator_ticked_get");
    return _ecore_animator_run_get();
 }
 
@@ -1047,6 +1372,7 @@ _ecore_main_fd_handler_add(int                    fd,
                            const void            *buf_data,
                            Eina_Bool              is_file)
 {
+   DBG("_ecore_main_fd_handler_add");
    Ecore_Fd_Handler *fdh = NULL;
 
    if ((fd < 0) || (flags == 0) || (!func)) return NULL;
@@ -1381,7 +1707,7 @@ _ecore_main_prepare_handlers(void)
      }
 }
 
-#ifndef USE_G_MAIN_LOOP
+#if !defined(USE_G_MAIN_LOOP)
 static int
 _ecore_main_select(double timeout)
 {
@@ -1750,8 +2076,119 @@ _ecore_main_fd_handlers_buf_call(void)
    return ret;
 }
 
-#ifndef USE_G_MAIN_LOOP
+#ifdef HAVE_LIBUV
+static void
+_ecore_main_loop_uv_prepare(uv_prepare_t* handle EINA_UNUSED)
+{
+   _ecore_lock();
+   _dl_uv_timer_stop(&_ecore_main_uv_handle_timers);
+   if(in_main_loop == 0 && do_quit)
+     {
+       _ecore_main_fd_handlers_cleanup();
+
+       while (fd_handlers)
+         {
+           Ecore_Fd_Handler *fdh;
+
+           fdh = fd_handlers;
+           fd_handlers = (Ecore_Fd_Handler *)eina_inlist_remove(EINA_INLIST_GET(fd_handlers),
+                                                                EINA_INLIST_GET(fdh));
+           _ecore_main_fdh_poll_del(fdh);
+           ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
+           ecore_fd_handler_mp_free(fdh);
+         }
+       if (fd_handlers_with_buffer)
+         fd_handlers_with_buffer = eina_list_free(fd_handlers_with_buffer);
+       if (fd_handlers_with_prep)
+         fd_handlers_with_prep = eina_list_free(fd_handlers_with_prep);
+       if (fd_handlers_to_delete)
+         fd_handlers_to_delete = eina_list_free(fd_handlers_to_delete);
+       if (file_fd_handlers)
+         file_fd_handlers = eina_list_free(file_fd_handlers);
+
+       fd_handlers_to_call = NULL;
+       fd_handlers_to_call_current = NULL;
+       fd_handlers_to_delete = NULL;
+       fd_handler_current = NULL;
+       
+       _dl_uv_prepare_stop(&_ecore_main_uv_prepare);
+       _dl_uv_check_stop(&_ecore_main_uv_check);
+       _dl_uv_stop(_dl_uv_default_loop());
+
+       _ecore_unlock();
+       return;
+     }
+   
+   in_main_loop++;
+  
+   if(!_ecore_main_uv_idling)
+     {
+        _ecore_main_uv_idling = EINA_TRUE;
+        _ecore_idle_enterer_call();
+        _ecore_throttle();
+     }
+
+   double t = -1;
+   if(_ecore_main_uv_idling)
+     {
+       _ecore_idler_all_call();
+       DBG("called idles");
+       if(_ecore_idler_exist() || _ecore_event_exist())
+         t = 0.0;
+     }
+
+   if (do_quit)
+     {
+       DBG("do quit outside loop");
+
+       if(_ecore_main_uv_idling)
+         {
+            _ecore_idle_exiter_call();
+            _ecore_animator_run_reset();
+       
+            _ecore_main_uv_idling = EINA_FALSE;
+         }
+
+       t = -1;
+
+       _ecore_time_loop_time = ecore_time_get();
+       _ecore_timer_enable_new();
+
+       goto done;
+     }
+
+   assert(!fd_handlers_to_call);
+
+   _ecore_time_loop_time = ecore_time_get();
+   _ecore_timer_enable_new();
+   if (_ecore_timers_exists() || t >= 0)
+     {
+       double t1 = _ecore_timer_next_get();
+       if(t < 0 || (t1 >= 0 && t1 < t)) t = t1;
+       DBG("Should awake after %f", t);
+       
+       if (t >= 0.0)
+         {
+           //_dl_uv_timer_stop(&_ecore_main_uv_handle_timers);
+           _dl_uv_timer_start(&_ecore_main_uv_handle_timers, &_ecore_main_loop_timer_run, t * 1000
+                              , 0);
+         }
+       else
+         DBG("Is not going to awake with timer");
+     }
+   else
+     DBG("Is not going to awake with timer");
+
+ done:
+   if (fd_handlers_with_prep)
+     _ecore_main_prepare_handlers();
+
+   _ecore_unlock();
+   in_main_loop--;
+}
+#endif
 
+#if !defined(USE_G_MAIN_LOOP)
 enum {
    SPIN_MORE,
    SPIN_RESTART,
index a8676a2..c59ecfa 100644 (file)
@@ -450,7 +450,7 @@ GENERIC_ALLOC_FREE_HEADER(Ecore_Win32_Handler, ecore_win32_handler);
 
 extern Eo *_ecore_parent;
 #define ECORE_PARENT_CLASS ecore_parent_class_get()
-const Eo_Class *ecore_parent_class_get(void) EINA_CONST;
+EAPI const Eo_Class *ecore_parent_class_get(void) EINA_CONST;
 
 #undef EAPI
 #define EAPI
index 4f1b7df..0498d3c 100644 (file)
  * @{
  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef Eo Ecore_Con_Eet;
 typedef struct _Ecore_Con_Reply Ecore_Con_Reply;
 
@@ -300,4 +304,11 @@ EAPI void ecore_con_eet_raw_send(Ecore_Con_Reply *reply, const char *protocol_na
  * @}
  */
 
+#ifdef __cplusplus
+}
+#endif
+
+#undef EAPI
+#define EAPI
+  
 #endif
index 2dfa99a..494c131 100644 (file)
@@ -58,7 +58,7 @@ interface Efl.Model.Base ()
                return: Efl.Model.Load_Status;
          }
          values {
-               properties: const(array<const(char*)>*); [[array of current properties]]
+               properties: const(array<const(char)*>*); [[array of current properties]]
             }
         }
          @property property {
index e2d7a7a..3ea7863 100644 (file)
 # endif
 #endif /* ! _WIN32 */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifndef EFL_NOLEGACY_API_SUPPORT
 #include "Emotion_Legacy.h"
 #endif
@@ -266,26 +270,23 @@ typedef enum _Emotion_Aspect    Emotion_Aspect; /**< Aspect ratio option. */
 #define EMOTION_CHANNEL_AUTO -1
 #define EMOTION_CHANNEL_DEFAULT 0
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define EMOTION_VERSION_MAJOR EFL_VERSION_MAJOR
 #define EMOTION_VERSION_MINOR EFL_VERSION_MINOR
-   /**
-    * @typedef Emotion_Version
-    * Represents the current version of Emotion
-    */
-   typedef struct _Emotion_Version
-     {
-        int major; /** < major (binary or source incompatible changes) */
-        int minor; /** < minor (new features, bugfixes, major improvements version) */
-        int micro; /** < micro (bugfix, internal improvements, no new features version) */
-        int revision; /** < git revision (0 if a proper release or the git revision number Emotion is built from) */
-     } Emotion_Version;
-   
-   EAPI extern Emotion_Version *emotion_version;
-   
+
+/**
+ * @typedef Emotion_Version
+ * Represents the current version of Emotion
+ */
+typedef struct _Emotion_Version
+  {
+     int major; /** < major (binary or source incompatible changes) */
+     int minor; /** < minor (new features, bugfixes, major improvements version) */
+     int micro; /** < micro (bugfix, internal improvements, no new features version) */
+     int revision; /** < git revision (0 if a proper release or the git revision number Emotion is built from) */
+  } Emotion_Version;
+
+EAPI extern Emotion_Version *emotion_version;
+
 /* api calls available */
 
 /**
@@ -873,7 +874,7 @@ EAPI Eina_Bool    emotion_object_smooth_scale_get      (const Evas_Object *obj);
  * @param obj The object target of the event.
  * @param ev The emotion event.
  *
- * @see Emotion_Event 
+ * @see Emotion_Event
  */
 EAPI void         emotion_object_event_simple_send     (Evas_Object *obj, Emotion_Event ev);
 
index ea1130e..969780a 100644 (file)
@@ -1964,6 +1964,7 @@ _emotion_object_evas_object_smart_clip_unset(Evas_Object *obj EINA_UNUSED, Emoti
    if (sd->crop.clipper) evas_object_clip_unset(sd->crop.clipper);
    else evas_object_clip_unset(sd->obj);
    evas_object_clip_unset(sd->bg);
+
 }
 
 #include "emotion_object.eo.c"
index fc450c2..ad70c0c 100644 (file)
@@ -535,15 +535,15 @@ typedef struct _Eo_Call_Cache
   }
 
 #ifndef _WIN32
-# define _EO_OP_API_ENTRY(a) a
+# define _EO_OP_API_ENTRY(a) (void*)a
 #else
 # define _EO_OP_API_ENTRY(a) #a
 #endif
 
-#define EO_OP_FUNC(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_TYPE_REGULAR }
-#define EO_OP_CLASS_FUNC(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_TYPE_CLASS }
-#define EO_OP_FUNC_OVERRIDE(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_TYPE_REGULAR_OVERRIDE }
-#define EO_OP_CLASS_FUNC_OVERRIDE(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_TYPE_CLASS_OVERRIDE }
+#define EO_OP_FUNC(_api, _private) { _EO_OP_API_ENTRY(_api), (void*)_private, EO_OP_TYPE_REGULAR }
+#define EO_OP_CLASS_FUNC(_api, _private) { _EO_OP_API_ENTRY(_api), (void*)_private, EO_OP_TYPE_CLASS }
+#define EO_OP_FUNC_OVERRIDE(_api, _private) { _EO_OP_API_ENTRY(_api), (void*)_private, EO_OP_TYPE_REGULAR_OVERRIDE }
+#define EO_OP_CLASS_FUNC_OVERRIDE(_api, _private) { _EO_OP_API_ENTRY(_api), (void*)_private, EO_OP_TYPE_CLASS_OVERRIDE }
 
 // returns the OP id corresponding to the given api_func
 EAPI Eo_Op _eo_api_op_id_get(const void *api_func);
index e69225d..741adfc 100644 (file)
@@ -2,4 +2,5 @@ check-results.xml
 *_suite
 *_suite.log
 *_suite.trs
+*.node
 */cxx_compile_test
index a5331b4..968a7ec 100644 (file)
@@ -267,6 +267,39 @@ START_TEST(ecore_test_ecore_main_loop_fd_handler)
 }
 END_TEST
 
+START_TEST(ecore_test_ecore_main_loop_fd_handler_activate_modify)
+{
+   Eina_Bool did = EINA_FALSE;
+   Ecore_Fd_Handler *fd_handler;
+   int comm[2];
+   int ret;
+
+   ret = ecore_init();
+   fail_if(ret < 1);
+
+   ret = pipe(comm);
+   fail_if(ret != 0);
+
+   fd_handler = ecore_main_fd_handler_add
+     (comm[0], ECORE_FD_ERROR, _fd_handler_cb, &did, NULL, NULL);
+   fail_if(fd_handler == NULL);
+
+   ecore_main_fd_handler_active_set(fd_handler, ECORE_FD_READ);
+
+   ret = write(comm[1], "e", 1);
+   fail_if(ret != 1);
+
+   ecore_main_loop_begin();
+
+   close(comm[0]);
+   close(comm[1]);
+
+   fail_if(did != EINA_TRUE);
+
+   ret = ecore_shutdown();
+}
+END_TEST
+
 static Eina_Bool
 _event_handler_cb(void *data, int type, void *event)
 {
@@ -705,6 +738,7 @@ void ecore_test_ecore(TCase *tc)
    tcase_add_test(tc, ecore_test_ecore_main_loop_idle_exiter);
    tcase_add_test(tc, ecore_test_ecore_main_loop_timer);
    tcase_add_test(tc, ecore_test_ecore_main_loop_fd_handler);
+   tcase_add_test(tc, ecore_test_ecore_main_loop_fd_handler_activate_modify);
    tcase_add_test(tc, ecore_test_ecore_main_loop_event);
    tcase_add_test(tc, ecore_test_ecore_main_loop_timer_inner);
    tcase_add_test(tc, ecore_test_ecore_main_loop_event_recursive);
index 18471fa..8baa9a5 100644 (file)
@@ -2,10 +2,10 @@
 # include <config.h>
 #endif
 
-#include <Ecore_X.h>
-
 #include "ecore_suite.h"
 
+#include <Eina.h>
+
 /* FIXME: Currently disable these tests. They are useless ATM and they just
  * make buildbot complain. Once we add useful tests here we'll also bother
  * with getting X on the server. */
@@ -14,6 +14,8 @@
 /* TODO: change to HAVE_ECORE_X when xcb implementation is done */
 #ifdef HAVE_ECORE_X_XLIB
 
+#include <Ecore_X.h>
+
 START_TEST(ecore_test_ecore_x_init)
 {
    int ret;
diff --git a/src/tests/efl_js/benchmark_js_suite.cc b/src/tests/efl_js/benchmark_js_suite.cc
new file mode 100644 (file)
index 0000000..c7583f2
--- /dev/null
@@ -0,0 +1,7 @@
+
+#include "suite_runner.hh"
+
+int main(int, char*[])
+{
+  return run_script(TESTS_SRC_DIR "/ecore_js_suite.js", nullptr);
+}
diff --git a/src/tests/efl_js/benchmark_js_suite.js b/src/tests/efl_js/benchmark_js_suite.js
new file mode 100755 (executable)
index 0000000..b3a5d7c
--- /dev/null
@@ -0,0 +1,205 @@
+#!/usr/bin/env node
+
+// Preamble
+function assert(condition, message) {
+  if (!condition) {
+      print("Assertion failed ", message);
+      throw new Error(message || "Assertion failed");
+  }
+}
+
+if(typeof process !== 'undefined')
+{
+    console.log('running from nodejs');
+    console.log('path', process.env.NODE_PATH);
+
+    efl = require('efl');
+    assert(efl != null, "could not load efl node module");
+
+    // Setup output aliases
+    print = console.log;
+    print_error = function() {
+        if (process.argv.indexOf("--supress-errors") == -1)
+            console.error.apply(null, arguments);
+    };
+    print_info = function() {
+        if (process.argv.indexOf("--verbose") != -1)
+            console.info.apply(null, arguments);
+    };
+    exit = efl.ecore_mainloop_quit;
+}
+else
+{
+    assert = function(test, message) { if (test !== true) throw message; };
+    print('running from libv8')
+    //FIXME Add levels to v8 tests
+    print_error = print
+    print_info = print
+    exit = function() {}
+}
+
+// Global flag for suite success //
+suite_success = true;
+// Global test summary
+suite_ok = 0;
+suite_fail = []; // Will store the name of the failures
+
+// Basic test function //
+function start_test(test_name, test_func) {
+  print("[ RUN         ]  eina_js_suite: " + test_name);
+  var test_result = true;
+  try {
+    test_func();
+  } catch (e) {
+    suite_success = false;
+    test_result = false;
+    print_error("Error: ", e, e.stack);
+  }
+  print("[        " + (test_result ? "PASS" : "FAIL") + " ]  eina_js_suite: " + test_name);
+  if (test_result)
+    suite_ok += 1;
+  else
+    suite_fail.push(test_name);
+}
+// end Preamble
+if (typeof process != "undefined")
+{
+    benchmark = require('benchmark_object');
+    assert(benchmark != null, "could not load benchmark_object.node");
+    Benchmark_Object = benchmark.BenchmarkObject;
+    benchmark_emptyarg = benchmark.benchmark_emptyarg;
+    benchmark_onearg = benchmark.benchmark_onearg;
+    benchmark_twoarg = benchmark.benchmark_twoarg;
+    benchmark_tenarg = benchmark.benchmark_tenarg;
+    benchmark_onecomplexarg = benchmark.benchmark_onecomplexarg;
+    benchmark_tencomplexarg = benchmark.benchmark_tencomplexarg;
+}
+else
+{
+    Benchmark_Object = suite.Benchmark_Object;
+}
+
+start_test("empty function", function(){
+    object = new Benchmark_Object(null);
+
+    for(i = 0; i != 10; i++)
+    {
+        object.emptyarg();
+    }
+    
+    time = process.hrtime();
+    for(i = 0; i != 20000; i++)
+    {
+        object.emptyarg();
+    }
+    time = process.hrtime(time);
+    console.log('JS empty function %d', time[0]*1000000000 + time[1]);
+    benchmark_emptyarg();    
+});
+
+start_test("onearg function", function(){
+    object = new Benchmark_Object(null);
+    for(i = 0; i != 10; i++)
+    {
+        object.onearg(1);
+    }
+
+    time = process.hrtime();
+    for(i = 0; i != 20000; i++)
+    {
+        object.onearg(1);
+    }
+    time = process.hrtime(time);
+    console.log('JS onearg function %d', time[0]*1000000000 + time[1]);
+
+    benchmark_onearg();    
+});
+
+start_test("twoarg function", function(){
+    object = new Benchmark_Object(null);
+    for(i = 0; i != 10; i++)
+    {
+        object.twoarg(1, 2);
+    }
+
+    time = process.hrtime();
+    for(i = 0; i != 20000; i++)
+    {
+        object.twoarg(1, 2);
+    }
+    time = process.hrtime(time);
+    console.log('JS twoarg function %d', time[0]*1000000000 + time[1]);
+
+    benchmark_twoarg();    
+});
+
+start_test("tenarg function", function(){
+    object = new Benchmark_Object(null);
+    for(i = 0; i != 10; i++)
+    {
+        object.tenarg(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    }
+
+    time = process.hrtime();
+    for(i = 0; i != 20000; i++)
+    {
+        object.tenarg(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    }
+    time = process.hrtime(time);
+    console.log('JS tenarg function %d', time[0]*1000000000 + time[1]);
+    benchmark_tenarg();    
+});
+
+start_test("onecomplexarg function", function(){
+    object = new Benchmark_Object(null);
+    list = new efl.List('int')
+    for(i = 0; i != 10; i++)
+    {
+        object.onecomplexarg(list);
+    }
+
+    time = process.hrtime();
+    for(i = 0; i != 20000; i++)
+    {
+        object.onecomplexarg(list);
+    }
+    time = process.hrtime(time);
+    console.log('JS onecomplexarg function %d', time[0]*1000000000 + time[1]);
+    benchmark_onecomplexarg();    
+});
+
+start_test("tencomplexarg function", function(){
+    object = new Benchmark_Object(null);
+    list = new efl.List('int')
+    for(i = 0; i != 10; i++)
+    {
+        object.tencomplexarg(list, list, list, list, list, list, list, list, list, list);
+    }
+
+    time = process.hrtime();
+    for(i = 0; i != 20000; i++)
+    {
+        object.tencomplexarg(list, list, list, list, list, list, list, list, list, list);
+    }
+    time = process.hrtime(time);
+    console.log('JS tencomplexarg function %d', time[0]*1000000000 + time[1]);
+    benchmark_tencomplexarg();    
+});
+
+// footer
+
+if (!suite_success) {
+  print ("[ Total tests run: %s ]", suite_ok + suite_fail.length);
+  print ("[ Total successful: %s ]", suite_ok);
+  print ("[ Total failures: %s ]", suite_fail.length);
+  print ("[ Tests failed: ]");
+  for (var i = 0; i < suite_fail.length; i++) {
+    print ("[    %s]", suite_fail[i]);
+  };
+  assert(false, "[ Test suite fail ]");
+} else {
+  print ("[ Test execution with success ]");
+  print ("[ Total tests run: %s ]", suite_ok);
+}
+
+exit();
diff --git a/src/tests/efl_js/benchmark_object.eo b/src/tests/efl_js/benchmark_object.eo
new file mode 100644 (file)
index 0000000..34dd142
--- /dev/null
@@ -0,0 +1,24 @@
+class Benchmark_Object (Eo.Base)
+{
+   legacy_prefix: null;
+   data: null;
+   methods {
+      emptyarg {
+      }
+      onearg {
+         params { one: int; }
+      }
+      twoarg {
+         params { one: int; two: int; }
+      }
+      tenarg {
+         params { one: int; two: int; three: int; four: int; five: int; six: int; seven: int; eight: int; nine: int; ten: int; }
+      }
+      onecomplexarg {
+         params { one: list<int>*; }
+      }
+      tencomplexarg {
+         params { one: list<int>*; two: list<int>*; three: list<int>*; four: list<int>*; five: list<int>*; six: list<int>*; seven: list<int>*; eight: list<int>*; nine: list<int>*; ten: list<int>*; }
+      }
+   }
+}
diff --git a/src/tests/efl_js/benchmark_object_impl.cc b/src/tests/efl_js/benchmark_object_impl.cc
new file mode 100644 (file)
index 0000000..538c31b
--- /dev/null
@@ -0,0 +1,110 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eo.h>
+#include <Ecore.h>
+
+#include <stdlib.h>
+
+extern "C" {
+#include "benchmark_object.eo.h"
+
+void _benchmark_object_emptyarg(Eo*, void*)
+{
+}
+void _benchmark_object_onearg(Eo*, void*, int)
+{
+}
+void _benchmark_object_twoarg(Eo*, void*, int, int)
+{
+}
+void _benchmark_object_tenarg(Eo*, void*, int, int, int, int, int, int, int, int, int, int)
+{
+}
+void _benchmark_object_onecomplexarg(Eo*, void*, Eina_List*)
+{
+}
+void _benchmark_object_tencomplexarg(Eo*, void*, Eina_List*, Eina_List*, Eina_List*, Eina_List*, Eina_List*, Eina_List*, Eina_List*, Eina_List*, Eina_List*, Eina_List*)
+{
+}
+  
+#include "benchmark_object.eo.c"
+}
+
+#include "benchmark_object.eo.js.cc"
+
+#ifdef HAVE_NODEJS
+namespace {
+using efl::eina::js::compatibility_return_type;
+using efl::eina::js::compatibility_callback_info_type;
+using efl::eina::js::compatibility_return;
+using efl::eina::js::compatibility_new;
+
+#define JS_BENCHMARK_ARGS0(v)
+#define JS_BENCHMARK_ARGS1(v) v
+#define JS_BENCHMARK_ARGS2(v) v,v
+#define JS_BENCHMARK_ARGS10(v) v,v,v,v,v,v,v,v,v,v
+#define JS_BENCHMARK_FUNC(name, number, v)                              \
+  compatibility_return_type js_benchmark_object_##name##arg(compatibility_callback_info_type) \
+  {                                                                     \
+    Eina_Counter* counter = eina_counter_new("counter");                \
+    Eo* object = eo_add(BENCHMARK_OBJECT_CLASS, NULL);                  \
+    Eina_List* l = NULL;                                                \
+    (void)l;                                                            \
+    /* Warm */                                                          \
+    for(int i = 0; i != 10; i++)                                        \
+      {                                                                 \
+        eo_do(object, benchmark_object_##name##arg(JS_BENCHMARK_ARGS##number(v))); \
+      }                                                                 \
+    /* Real loop */                                                     \
+    eina_counter_start(counter);                                        \
+    for(int i = 0; i != 20000; i++)                                     \
+      {                                                                 \
+        eo_do(object, benchmark_object_##name##arg(JS_BENCHMARK_ARGS##number(v))); \
+      }                                                                 \
+    eina_counter_stop(counter, 20000);                                  \
+    fprintf(stderr, "%s", eina_counter_dump(counter));                  \
+    eo_del(object);                                                     \
+    return compatibility_return();                                      \
+  }
+
+JS_BENCHMARK_FUNC(empty, 0, 1)
+JS_BENCHMARK_FUNC(one, 1, 1)
+JS_BENCHMARK_FUNC(two, 2, 1)
+JS_BENCHMARK_FUNC(ten, 10, 1)
+JS_BENCHMARK_FUNC(onecomplex, 1, l)
+JS_BENCHMARK_FUNC(tencomplex, 10, l)
+
+  
+void benchmark_object_module_init(v8::Handle<v8::Object> exports)
+{
+  fprintf(stderr, "test suite eolian_js_module_init\n"); fflush(stderr);
+  try
+    {
+       eina_init();
+       eo_init();
+       register_benchmark_object(exports, v8::Isolate::GetCurrent());
+#define JS_BENCHMARK_EXPORT(name)                                       \
+       exports->Set(compatibility_new<v8::String>(nullptr, "benchmark_" #name "arg") \
+                    , compatibility_new<v8::FunctionTemplate>(nullptr, &js_benchmark_object_##name##arg)->GetFunction());
+       JS_BENCHMARK_EXPORT(empty)
+       JS_BENCHMARK_EXPORT(one)
+       JS_BENCHMARK_EXPORT(two)
+       JS_BENCHMARK_EXPORT(ten)
+       JS_BENCHMARK_EXPORT(onecomplex)
+       JS_BENCHMARK_EXPORT(tencomplex)
+    }
+  catch(...)
+    {
+       std::cerr << "Error" << std::endl;
+       std::abort();
+    }
+}
+
+}
+
+#include <eina_js_node.hh>
+
+NODE_MODULE(benchmark_object, ::benchmark_object_module_init)
+#endif
diff --git a/src/tests/efl_js/ecore_js_suite.cc b/src/tests/efl_js/ecore_js_suite.cc
new file mode 100644 (file)
index 0000000..c7583f2
--- /dev/null
@@ -0,0 +1,7 @@
+
+#include "suite_runner.hh"
+
+int main(int, char*[])
+{
+  return run_script(TESTS_SRC_DIR "/ecore_js_suite.js", nullptr);
+}
diff --git a/src/tests/efl_js/ecore_js_suite.js b/src/tests/efl_js/ecore_js_suite.js
new file mode 100755 (executable)
index 0000000..8534304
--- /dev/null
@@ -0,0 +1,352 @@
+#!/usr/bin/env node
+
+// Preamble
+function assert(condition, message) {
+  if (!condition) {
+      print("Assertion failed ", message);
+      throw new Error(message || "Assertion failed");
+  }
+}
+
+if(typeof process !== 'undefined')
+{
+    console.log('running from nodejs');
+    console.log('path', process.env.NODE_PATH);
+    console.log("teste1");
+
+    efl = require('efl');
+    assert(efl != null, "could not load efl node module");
+
+    // Setup output aliases
+    print = console.log;
+    print_error = function() {
+        if (process.argv.indexOf("--supress-errors") == -1)
+            console.error.apply(null, arguments);
+    };
+    print_info = function() {
+        if (process.argv.indexOf("--verbose") != -1)
+            console.info.apply(null, arguments);
+    };
+    exit = efl.ecore_mainloop_quit;
+}
+else
+{
+    assert = function(test, message) { if (test !== true) throw message; };
+    print('running from libv8')
+    //FIXME Add levels to v8 tests
+    print_error = print
+    print_info = print
+    exit = function() {}
+}
+
+// Global flag for suite success //
+suite_success = true;
+// Global test summary
+suite_ok = 0;
+suite_fail = []; // Will store the name of the failures
+
+// Basic test function //
+function start_test(test_name, test_func) {
+  print("[ RUN         ]  ecore_js_suite: " + test_name);
+  var test_result = true;
+  try {
+    test_func();
+  } catch (e) {
+    suite_success = false;
+    test_result = false;
+    print_error("Error: ", e, e.stack);
+  }
+  print("[        " + (test_result ? "PASS" : "FAIL") + " ]  ecore_js_suite: " + test_name);
+  if (test_result)
+    suite_ok += 1;
+  else
+    suite_fail.push(test_name);
+}
+// end Preamble
+
+// ecore preamble
+function abs(n) {
+    if (n < 0)
+        return n * -1;
+    return n;
+}
+var TOLERANCE = 0.0001;
+// end ecore preamble
+
+start_test("timers", function () {
+    var p = 2.5;
+    efl.ecore_timer_precision_set(p);
+    assert(abs(efl.ecore_timer_precision_get() - p) < TOLERANCE);
+    
+    p = 0.5;
+    efl.ecore_timer_precision_set(p);
+    assert(abs(efl.ecore_timer_precision_get() - p) < TOLERANCE);
+    
+    var ncalls = 0;
+
+    captured = false;
+    efl.ecore_timer_add(1, function() {
+        print_info('ecore_timer_add handler');
+        ++ncalls;
+        if (ncalls != 4)
+            return true;
+        
+        captured = true;
+        efl.ecore_job_add(efl.ecore_mainloop_quit);
+        return false;
+    });
+
+    efl.ecore_mainloop_begin();
+    assert(captured);
+
+    ncalls = 0;
+    captured = false;
+
+    efl.ecore_timer_loop_add(1, function() {
+        ++ncalls;
+        if (ncalls != 4)
+            return true;
+
+        captured = true;
+        efl.ecore_job_add(efl.ecore_mainloop_quit);
+        return false;
+    });
+
+    efl.ecore_mainloop_begin();
+    assert(captured);
+
+    captured = false;
+
+    var timer = efl.ecore_timer_add(1, function() {
+        captured = true;
+        return false;
+    });
+
+    assert(timer.freeze_get() === false);
+
+    timer.freeze();
+
+    assert(timer.freeze_get() === true);
+
+    timer.thaw();
+
+    assert(timer.freeze_get() === false);
+
+    timer.del();
+
+    efl.ecore_timer_add(2, function() {
+        efl.ecore_job_add(efl.ecore_mainloop_quit);
+        return false;
+    });
+
+    efl.ecore_mainloop_begin();
+    assert(captured === false);
+});
+
+// Ecore event
+start_test("ecore event", function () {
+    var myevent = efl.ecore_event_type_new();
+
+    captured = [0, 0, 0]
+
+    var handler1 = efl.ecore_event_handler_add(myevent, function(event) {
+        assert(efl.ecore_event_current_type_get() === myevent);
+        assert(event === myevent);
+        captured[0] += 1;
+        return efl.ECORE_CALLBACK_PASS_ON;
+    });
+
+    var handler2 = efl.ecore_event_handler_add(myevent, function(event) {
+        assert(efl.ecore_event_current_type_get() === myevent);
+        assert(event === myevent);
+        captured[1] += 1;
+        return efl.ECORE_CALLBACK_DONE;
+    });
+
+    var handler3 = efl.ecore_event_handler_add(myevent, function(event) {
+        assert(efl.ecore_event_current_type_get() === myevent);
+        assert(event === myevent);
+        captured[2] += 1;
+        return efl.ECORE_CALLBACK_DONE;
+    });
+
+    efl.ecore_timer_add(1, function() {
+        efl.ecore_event_add(myevent);
+        assert(captured[0] === 0 && captured[1] === 0 && captured[2] === 0);
+        efl.ecore_timer_add(1, function() {
+            assert(captured[0] === 1 && captured[1] === 1 && captured[2] === 0);
+            handler1.del();
+            efl.ecore_event_add(myevent);
+            efl.ecore_event_add(myevent);
+            efl.ecore_event_add(myevent).del();
+            efl.ecore_timer_add(1, function() {
+                assert(captured[0] === 1 && captured[1] === 3 && captured[2] === 0);
+                efl.ecore_mainloop_quit();
+            });
+        });
+    });
+
+    efl.ecore_mainloop_begin();
+
+    efl.ecore_event_add(myevent);
+    efl.ecore_event_add(myevent);
+    efl.ecore_event_add(myevent);
+
+    var filter = efl.ecore_event_filter_add(function() {
+        return {count: 0};
+    }, function(loop_data, event) {
+        assert(event === myevent);
+        var c = loop_data.count;
+        ++loop_data.count;
+        return c != 0;
+    }, function(loop_data) {});
+    
+    efl.ecore_timer_add(1, efl.ecore_mainloop_quit);
+    efl.ecore_mainloop_begin();
+    assert(captured[1] === 5);
+    filter.del();
+
+    efl.ecore_event_add(myevent);
+    efl.ecore_event_add(myevent);
+    efl.ecore_event_add(myevent);
+    
+    efl.ecore_timer_add(1, efl.ecore_mainloop_quit);
+    efl.ecore_mainloop_begin();
+    assert(captured[1] === 8);
+
+    handler2.del();
+    handler3.del();
+});
+
+    // Ecore job
+start_test("ecore jobs", function () {
+    captured = false;
+
+    efl.ecore_job_add(function() {
+        captured = true;
+        efl.ecore_mainloop_quit();
+    });
+
+    assert(captured === false);
+    efl.ecore_mainloop_begin();
+    assert(captured === true);
+
+    captured = false;
+    var job = efl.ecore_job_add(function() {
+        captured = true;
+    });
+    efl.ecore_job_add(efl.ecore_mainloop_quit);
+    job.del();
+    efl.ecore_mainloop_begin();
+    assert(captured === false);
+});
+
+start_test("ecore idle", function () {
+    // Ecore idle
+    var counter = 1;
+    captured = [0, 0, 0, 0, 0];
+
+    efl.ecore_idler_add(function() {
+        print_info('ecore idle handler 1');
+        captured[0] = counter;
+        counter += 1;
+        efl.ecore_job_add(function() { print_info('ecore job handler 1'); });
+        return efl.ECORE_CALLBACK_DONE;
+    });
+
+    print_info('ecore idle 1');
+
+    efl.ecore_idle_enterer_add(function() {
+        print_info('ecore idle handler 2');
+        captured[1] = counter;
+        counter += 1;
+        return efl.ECORE_CALLBACK_DONE;
+    });
+
+    print_info('ecore idle 2');
+
+    efl.ecore_idle_enterer_add(function() {
+        print_info('ecore idle handler 3');
+        captured[2] = counter;
+        counter += 1;
+        return efl.ECORE_CALLBACK_DONE;
+    });
+
+    print_info('ecore idle 3');
+
+    efl.ecore_idle_enterer_before_add(function() {
+        print_info('ecore idle handler 4');
+        captured[3] = counter;
+        counter += 1;
+        return efl.ECORE_CALLBACK_DONE;
+    });
+
+    print_info('ecore idle 4');
+
+    efl.ecore_idle_exiter_add(function() {
+        print_info('ecore idle handler 5');
+        captured[4] = counter;
+        counter += 1;
+        efl.ecore_mainloop_quit();
+        return efl.ECORE_CALLBACK_DONE;
+    });
+
+    print_info('ecore idle 5');
+
+    efl.ecore_mainloop_begin();
+
+    print_info('ecore idle 6');
+
+    assert(captured[0] === 4, "ecore_idler_add test");
+    assert(captured[1] === 2, "ecore_idle_enterer_add test");
+    assert(captured[2] === 3, "ecore_idle_enterer_add test two");
+    assert(captured[3] === 1, "ecore_idle_enterer_before_add test");
+    assert(captured[4] === 5, "ecore_idle_exiter_add test");
+});
+
+// Ecore animator
+start_test("ecore animator", function () {
+    efl.ecore_animator_frametime_set(1);
+    assert(efl.ecore_animator_frametime_get() === 1);
+    efl.ecore_animator_frametime_set(1 / 50);
+    assert(efl.ecore_animator_frametime_get() === (1 / 50));
+
+    assert(efl.ecore_animator_pos_map(0.5, efl.ECORE_POS_MAP_LINEAR, 0, 0)
+           === 0.5);
+
+    efl.ecore_animator_source_set(efl.ECORE_ANIMATOR_SOURCE_CUSTOM);
+});
+
+// Ecore poller
+start_test("ecore poller", function () {
+    efl.ecore_poller_poll_interval_set(efl.ECORE_POLLER_CORE, 42);
+    assert(efl.ecore_poller_poll_interval_get(efl.ECORE_POLLER_CORE) === 42);
+    efl.ecore_poller_poll_interval_set(efl.ECORE_POLLER_CORE, 2);
+    assert(efl.ecore_poller_poll_interval_get(efl.ECORE_POLLER_CORE) === 2);
+});
+
+start_test("ecore throttle", function () {
+    // Ecore throttle
+
+    efl.ecore_throttle_adjust(3);
+    assert(efl.ecore_throttle_get() === 3);
+    efl.ecore_throttle_adjust(-3);
+    assert(efl.ecore_throttle_get() === 0);
+});
+
+// footer
+if (!suite_success) {
+  print ("[ Total tests run: %s ]", suite_ok + suite_fail.length);
+  print ("[ Total successful: %s ]", suite_ok);
+  print ("[ Total failures: %s ]", suite_fail.length);
+  print ("[ Tests failed: ]");
+  for (var i = 0; i < suite_fail.length; i++) {
+    print ("[    %s]", suite_fail[i]);
+  };
+  assert(false, "[ Test suite fail ]");
+} else {
+  print ("[ Test execution with success ]");
+  print ("[ Total tests run: %s ]", suite_ok);
+}
+
+exit();
diff --git a/src/tests/efl_js/eina_js_containers_suite.cc b/src/tests/efl_js/eina_js_containers_suite.cc
new file mode 100644 (file)
index 0000000..5455b94
--- /dev/null
@@ -0,0 +1,7 @@
+
+#include "suite_runner.hh"
+
+int main(int, char*[])
+{
+  return run_script(TESTS_SRC_DIR "/eina_js_containers_suite.js", nullptr);
+}
diff --git a/src/tests/efl_js/eina_js_containers_suite.js b/src/tests/efl_js/eina_js_containers_suite.js
new file mode 100755 (executable)
index 0000000..f4f6bf3
--- /dev/null
@@ -0,0 +1,552 @@
+#!/usr/bin/env node
+
+// Preamble
+function assert(condition, message) {
+  if (!condition) {
+      print("Assertion failed ", message);
+      throw new Error(message || "Assertion failed");
+  }
+}
+
+if(typeof process !== 'undefined')
+{
+    console.log('running from nodejs');
+    console.log('path', process.env.NODE_PATH);
+    console.log("teste1");
+
+    efl = require('efl');
+    assert(efl != null, "could not load efl node module");
+
+    // Setup output aliases
+    print = console.log;
+    print_error = function() {
+        if (process.argv.indexOf("--supress-errors") == -1)
+            console.error.apply(null, arguments);
+    };
+    print_info = function() {
+        if (process.argv.indexOf("--verbose") != -1)
+            console.info.apply(null, arguments);
+    };
+    exit = efl.ecore_mainloop_quit;
+}
+else
+{
+    assert = function(test, message) { if (test !== true) throw message; };
+    print('running from libv8')
+    //FIXME Add levels to v8 tests
+    print_error = print
+    print_info = print
+    exit = function() {}
+}
+
+// Global flag for suite success //
+suite_success = true;
+// Global test summary
+suite_ok = 0;
+suite_fail = []; // Will store the name of the failures
+
+// Basic test function //
+function start_test(test_name, test_func) {
+  print("[ RUN         ]  eina_js_suite: " + test_name);
+  var test_result = true;
+  try {
+    test_func();
+  } catch (e) {
+    suite_success = false;
+    test_result = false;
+    print_error("Error: ", e, e.stack);
+  }
+  print("[        " + (test_result ? "PASS" : "FAIL") + " ]  eina_js_suite: " + test_name);
+  if (test_result)
+    suite_ok += 1;
+  else
+    suite_fail.push(test_name);
+}
+// end Preamble
+
+start_test("container_test default list should have size zero", function(){
+  var container = new efl.List;
+  assert (container.length == 0);
+});
+
+start_test("container test default Array should have size zero", function(){
+  var container = new efl.Array;
+  assert (container.length == 0);
+});
+
+start_test("container_test empty list access should return undefined", function(){
+  var empty_l = new efl.List;
+  assert (typeof empty_l[0] === "undefined");
+  assert (typeof empty_l[1] === "undefined");
+});
+
+start_test("container_test empty Array access should return undefined", function(){
+  var empty_l = new efl.Array;
+  assert (typeof empty_l[0] === "undefined");
+  assert (typeof empty_l[1] === "undefined");
+});
+
+start_test("container_test empty list indexOf should return -1", function(){
+  var empty_l = new efl.List;
+  assert(empty_l.indexOf(0) == -1);
+  assert(empty_l.indexOf(42) == -1);
+});
+
+start_test("container_test empty Array indexOf should return -1", function(){
+  var empty_l = new efl.Array;
+  assert(empty_l.indexOf(0) == -1);
+  assert(empty_l.indexOf(42) == -1);
+});
+
+start_test("container_test List indexOf should not break with wrong type", function(){
+  container_indexof_wrong_type(efl.List);
+});
+
+start_test("container_test Array indexOf should not break with wrong type", function(){
+  container_indexof_wrong_type(efl.Array);
+});
+
+function container_indexof_wrong_type(T) {
+  var x = new T("int");
+  var raised = false;
+  try {
+    x.indexOf("float")
+  } catch (err) {
+    raised = true;
+  }
+
+  assert(!raised, "container index of should not break with wrong types");
+}
+
+start_test("container_test list[0] = x on empty list", function(){
+  var empty_l = new efl.List;
+  assert(empty_l.length == 0);
+  empty_l[0] = 42;
+  assert(empty_l.length == 1);
+  assert(empty_l[0] == 42);
+});
+
+start_test("container_test array[0] = x on empty Array", function(){
+  var empty_l = new efl.Array;
+  assert(empty_l.length == 0);
+  empty_l[0] = 42;
+  assert(empty_l.length == 1);
+  assert(empty_l[0] == 42);
+});
+
+start_test("container_test out of bounds x[i] setter should resize list", function(){
+  container_out_of_bound_setter(efl.List);
+});
+
+start_test("container_test out of bounds x[i] setter should resize Array", function(){
+  container_out_of_bound_setter(efl.Array);
+});
+
+function container_out_of_bound_setter(T1) {
+  var empty_l = new T1;
+  assert(empty_l.length == 0);
+  empty_l[9] = 1;
+  assert(empty_l.length == 10);
+  for (var i = 0; i < 9; i++) {
+    assert(empty_l[i] == 0);
+  };
+  assert(empty_l[9] == 1);
+}
+
+start_test("container_test push items should increase list length", function(){
+  container_push_length(efl.List);
+});
+
+start_test("container_test push items should increase Array length", function(){
+  container_push_length(efl.Array);
+});
+
+function container_push_length(T1) {
+  var l1 = new T1;
+  print_info("l1 ", l1.toString());
+  l1.push(1);
+  assert (l1.length == 1);
+  l1.push(2);
+  assert (l1.length == 2);
+  l1.push(3);
+  assert (l1.length == 3);
+}
+
+start_test("container_test list simple push and access valid items", function(){
+  container_push_access_valid(efl.List);
+});
+
+start_test("container_test Array simple push and access valid items", function(){
+  container_push_access_valid(efl.Array);
+});
+
+function container_push_access_valid(T1) {
+  var l1 = new T1;
+  l1.push(1);
+  l1.push(2);
+  assert (l1[0] == 1);
+  assert (l1[1] == 2);
+}
+
+start_test("container_test list simple push and access items out of bounds", function(){
+  container_push_out_of_bounds(efl.List);
+});
+
+start_test("container_test Array simple push and access items out of bounds", function(){
+  container_push_out_of_bounds(efl.Array);
+});
+
+function container_push_out_of_bounds(T1) {
+  var l1 = new T1;
+  l1.push(1);
+  l1.push(2);
+  assert (typeof l1[3] === "undefined");
+  assert (typeof l1[42] === "undefined");
+}
+
+start_test("container_test list push and pop", function() {
+  container_push_pop(efl.List);
+});
+
+start_test("container_test Array push and pop", function() {
+  container_push_pop(efl.Array);
+});
+
+function container_push_pop(T1) {
+  var l1 = new T1;
+
+  assert(typeof l1.pop() === "undefined", "pop on empty container should return undefined");
+
+  l1.push(1);
+  l1.push(2);
+  assert(l1.length == 2);
+  assert(l1.pop() == 2, "Pop should return last element");
+  assert(l1.length == 1, "Pop should decrease list length");
+  assert(l1.pop() == 1, "Pop should return last element even if it's the only element");
+  assert(l1.length == 0, "Pop on single element list should leave it empty");
+}
+
+start_test("container_test list simple push and indexOf valid elements", function(){
+  container_push_indexof_valid(efl.List)
+});
+
+start_test("container_test Array simple push and indexOf valid elements", function(){
+  container_push_indexof_valid(efl.Array)
+});
+
+function container_push_indexof_valid(T1) {
+  var l1 = new T1;
+  l1.push(1);
+  l1.push(2);
+  assert(l1.indexOf(1) == 0);
+  assert(l1.indexOf(2) == 1);
+}
+
+start_test("container_test list simple push and indexOf elements out of bounds", function(){
+  container_push_indexof_out_of_bounds(efl.List);
+});
+
+start_test("container_test list simple push and indexOf elements out of bounds", function(){
+  container_push_indexof_out_of_bounds(efl.Array);
+});
+
+function container_push_indexof_out_of_bounds(T1) {
+  var l1 = new T1;
+  l1.push(1);
+  l1.push(2);
+  assert(l1.indexOf(3) == -1);
+  assert(l1.indexOf(44) == -1);
+}
+
+start_test("container_test list concat filled + empty shouldn't change length", function(){
+  container_filled_concat_empty_length(efl.List);
+});
+
+start_test("container_test array concat filled + empty shouldn't change length", function(){
+  container_filled_concat_empty_length(efl.Array);
+});
+
+function container_filled_concat_empty_length(T1) {
+    var empty_l = new T1;
+    var l1 = new T1;
+    l1.push(1);
+    l1.push(2);
+    l1.push(3);
+    var cle = l1.concat(empty_l);
+    assert (cle.length == 3);
+}
+
+start_test("container_test list concat empty + filled shouldn't change length", function(){
+  container_empty_concat_filled_length(efl.List);
+});
+
+start_test("container_test array concat empty + filled shouldn't change length", function(){
+  container_empty_concat_filled_length(efl.Array);
+});
+
+function container_empty_concat_filled_length(T1) {
+    var empty_l = new T1;
+    var l1 = new T1;
+    l1.push(1);
+    l1.push(2);
+    l1.push(3);
+    var cel = empty_l.concat(l1);
+    assert (cel.length == 3);
+}
+
+start_test("container_test concat two valid lists", function(){
+  container_concat_two_valid_containers(efl.List, efl.List);
+});
+
+start_test("container_test concat two valid arrays", function(){
+  container_concat_two_valid_containers(efl.Array, efl.Array);
+});
+
+function container_concat_two_valid_containers(T1, T2) {
+    l1 = new T1;
+    l1.push(1);
+    l1.push(2);
+    l1.push(3);
+    l2 = new T2;
+    l2.push(1);
+    l2.push(2);
+    l2.push(3);
+    var c = l1.concat(l2);
+
+    assert (c.length == (l1.length + l2.length));
+    assert (c[0] == l1[0]);
+    assert (c[1] == l1[1]);
+    assert (c[2] == l1[2]);
+    assert (c[3] == l2[0]);
+    assert (c[4] == l2[1]);
+    assert (c[5] == l2[2]);
+    assert (c.indexOf(c[0]) == 0);
+    assert (c.indexOf(c[1]) == 1);
+    assert (c.indexOf(c[2]) == 2);
+    assert (c.indexOf(c[3]) == 0);
+    assert (c.indexOf(c[4]) == 1);
+    assert (c.indexOf(c[5]) == 2);
+    assert (c.lastIndexOf(c[0]) == 3);
+    assert (c.lastIndexOf(c[1]) == 4);
+    assert (c.lastIndexOf(c[2]) == 5);
+    assert (c.lastIndexOf(c[3]) == 3);
+    assert (c.lastIndexOf(c[4]) == 4);
+    assert (c.lastIndexOf(c[5]) == 5);
+}
+
+start_test("container_test concat different types", function() {
+  container_concat_diff_types(efl.Array, efl.List);
+  container_concat_diff_types(efl.List, efl.Array);
+});
+
+function container_concat_diff_types(T1, T2) {
+  var l1 = new T1;
+  var l2 = new T2;
+  var raised = false;
+
+  try {
+    l1.concat(l2);
+    assert(false, "Should raise exception after concatenating two different types.")
+  } catch (err) {
+    raised = true;
+    assert(err.name == "TypeError", "Exception should be TypeError.");
+  }
+
+  assert(raised, "Exception was not raised after concatenating different types.");
+}
+
+start_test("container_test toString list", function(){
+  container_to_string(efl.List);
+});
+
+start_test("container_test toString array", function(){
+  container_to_string(efl.Array);
+});
+
+function container_to_string(T) {
+  var x = new T("int");
+
+  assert("" == x.toString(), "toString empty container");
+
+  x.push(1);
+  assert("1" == x.toString(), "toString single element");
+
+  x.push(2);
+  assert("1,2" == x.toString(), "toString two elements");
+
+  x.push(100);
+  assert("1,2,100" == x.toString(), "toString three elements");
+}
+
+start_test("container_test join list", function(){
+  container_join(efl.List);
+});
+
+start_test("container_test join Array", function(){
+  container_join(efl.Array);
+});
+
+function container_join(T) {
+  var x = new T("int");
+  var ref = new Array;
+
+  assert(ref.join() == x.join(), "default join on empty containers");
+  assert(ref.join(':') == x.join(':'), "arg join on empty containers");
+
+  x.push(42);
+  ref.push(42);
+
+  assert(ref.join() == x.join(), "default join on single-element containers");
+  assert(ref.join(':') == x.join(':'), "arg join on single-element containers");
+
+  x.push(314);
+  ref.push(314);
+
+  assert(ref.join() == x.join(), "default join on multiple-element containers");
+  assert(ref.join(':') == x.join(':'), "arg join on multiple-element containers");
+}
+
+start_test("container_test join wrong arguments", function(){
+
+});
+
+function container_join_wrong_type(T1, T2) {
+  var l1 = new T1("int");
+  var raised = false;
+
+  try {
+    l1.join({});
+    assert(false, "Should raise exception after trying to join with wrong argument type.");
+  } catch (err) {
+    raised = true;
+    assert(err.name == "TypeError", "Exception should be TypeError.");
+  }
+
+  assert(raised, "Exception was not raised after join with wrong argument type.");
+}
+
+start_test("container_test slice list simple", function () {
+    container_slice_simple(efl.List);
+});
+
+start_test("container_test slice Array simple", function () {
+    container_slice_simple(efl.Array);
+});
+
+function container_slice_simple(T1) {
+    l1 = new T1;
+    l1.push(1);
+    l1.push(2);
+    l1.push(3);
+
+    var s1 = l1.slice(1, 3);
+    assert (s1.length == 2);
+    assert (s1[0] == l1[1]);
+    assert (s1[1] == l1[2]);
+}
+
+start_test("container_test slice list single argument", function() {
+    container_slice_single_arg(efl.List);
+});
+
+start_test("container_test slice Array single argument", function() {
+    container_slice_single_arg(efl.Array);
+});
+
+function container_slice_single_arg(T1) {
+    l1 = new T1;
+    l1.push(0);
+    l1.push(1);
+    l1.push(2);
+    l1.push(3);
+    l1.push(4);
+
+    var s1 = l1.slice(1);
+    assert(s1.length == (l1.length - 1));
+    assert(s1[0] == l1[1]);
+    assert(s1[1] == l1[2]);
+    assert(s1[2] == l1[3]);
+    assert(s1[3] == l1[4]);
+}
+
+start_test("container_test slice list no arguments", function() {
+    container_slice_no_args(efl.List);
+});
+
+start_test("container_test slice Array no arguments", function() {
+    container_slice_no_args(efl.Array);
+});
+
+function container_slice_no_args(T1) {
+    l1 = new T1;
+    l1.push(0);
+    l1.push(1);
+    l1.push(2);
+    l1.push(3);
+    l1.push(4);
+
+    var s1 = l1.slice();
+    assert(s1.length == l1.length);
+    assert(s1[0] == l1[0]);
+    assert(s1[1] == l1[1]);
+    assert(s1[2] == l1[2]);
+    assert(s1[3] == l1[3]);
+    assert(s1[4] == l1[4]);
+}
+
+start_test("container test list of strings", function(){
+  container_test_generic(new efl.List("string"), ["The", "quick", "brown", "fox"]);
+});
+
+start_test("container test array of strings", function(){
+  container_test_generic(new efl.Array("string"), ["The", "quick", "brown", "fox"]);
+});
+
+start_test("container test list of floats", function(){
+  container_test_generic(new efl.List("float"), [3.42, 3.14, 1.22, 0.0]);
+});
+
+start_test("container test Array of floats", function(){
+  container_test_generic(new efl.Array("float"), [3.42, 3.14, 1.22, 0.0]);
+});
+
+start_test("container test list of bools", function(){
+  container_test_generic(new efl.List("bool"), [true, false, false, false]);
+});
+
+start_test("container test array of bools", function(){
+  container_test_generic(new efl.Array("bool"), [true, false, false, false]);
+});
+
+function container_test_generic(list, js_ref_list) {
+  assert(list.length == 0);
+  list.push(js_ref_list[0]);
+  list.push(js_ref_list[1]);
+  list.push(js_ref_list[2]);
+  list.push(js_ref_list[3]);
+
+  assert(list.indexOf(js_ref_list[0]) == 0, "First pushed element has index 0");
+  assert(list.indexOf(js_ref_list[1]) == 1, "Second pushed element has index 1");
+  assert(list.lastIndexOf(js_ref_list[0]) == 0, "First element is unique, so its lastIndexOf should be 0");
+
+  assert(list.toString() == js_ref_list.toString(), "toString must be equal to JS.")
+  assert(list.pop() == js_ref_list[3], "Pop should return the last list element");
+}
+
+// footer
+
+if (!suite_success) {
+  print ("[ Total tests run: %s ]", suite_ok + suite_fail.length);
+  print ("[ Total successful: %s ]", suite_ok);
+  print ("[ Total failures: %s ]", suite_fail.length);
+  print ("[ Tests failed: ]");
+  for (var i = 0; i < suite_fail.length; i++) {
+    print ("[    %s]", suite_fail[i]);
+  };
+  assert(false, "[ Test suite fail ]");
+} else {
+  print ("[ Test execution with success ]");
+  print ("[ Total tests run: %s ]", suite_ok);
+}
+
+exit();
diff --git a/src/tests/efl_js/eina_js_suite.cc b/src/tests/efl_js/eina_js_suite.cc
new file mode 100644 (file)
index 0000000..68345b5
--- /dev/null
@@ -0,0 +1,7 @@
+
+#include "suite_runner.hh"
+
+int main(int, char*[])
+{
+  return run_script(TESTS_SRC_DIR "/eina_js_suite.js", nullptr);
+}
diff --git a/src/tests/efl_js/eina_js_suite.js b/src/tests/efl_js/eina_js_suite.js
new file mode 100755 (executable)
index 0000000..811e1f6
--- /dev/null
@@ -0,0 +1,360 @@
+#!/usr/bin/env node
+
+// Preamble
+function assert(condition, message) {
+  if (!condition) {
+      print("Assertion failed ", message);
+      throw new Error(message || "Assertion failed");
+  }
+}
+
+if(typeof process !== 'undefined')
+{
+    console.log('running from nodejs');
+    console.log('path', process.env.NODE_PATH);
+    console.log("teste1");
+
+    efl = require('efl');
+    assert(efl != null, "could not load efl node module");
+
+    // Setup output aliases
+    print = console.log;
+    print_error = function() {
+        if (process.argv.indexOf("--supress-errors") == -1)
+            console.error.apply(null, arguments);
+    };
+    print_info = function() {
+        if (process.argv.indexOf("--verbose") != -1)
+            console.info.apply(null, arguments);
+    };
+    exit = efl.ecore_mainloop_quit;
+}
+else
+{
+    assert = function(test, message) { if (test !== true) throw message; };
+    print('running from libv8')
+    //FIXME Add levels to v8 tests
+    print_error = print
+    print_info = print
+    exit = function() {}
+}
+
+// Global flag for suite success //
+suite_success = true;
+// Global test summary
+suite_ok = 0;
+suite_fail = []; // Will store the name of the failures
+
+// Basic test function //
+function start_test(test_name, test_func) {
+  print("[ RUN         ]  eina_js_suite: " + test_name);
+  var test_result = true;
+  try {
+    test_func();
+  } catch (e) {
+    suite_success = false;
+    test_result = false;
+    print_error("Error: ", e, e.stack);
+  }
+  print("[        " + (test_result ? "PASS" : "FAIL") + " ]  eina_js_suite: " + test_name);
+  if (test_result)
+    suite_ok += 1;
+  else
+    suite_fail.push(test_name);
+}
+
+function array_equal(a, b) {
+  if (a === b) return true;
+  if (a == null || b == null) return false;
+  if (a.length != b.length) return false;
+
+  for (var i = 0; i < a.length; ++i) {
+    if (a[i] !== b[i]
+        && (Object.prototype.toString.call(a[i]) === '[object Array]'
+             && Object.prototype.toString.call(b[i] === '[object Array]')
+             && !array_equal(a[i], b[i])))
+      return false;
+  }
+  return true;
+}
+// end Preamble
+
+// eina Preamble
+// Functions to get the line in NodeJS and V8
+Object.defineProperty(global, '__stack', {
+get: function() {
+        var orig = Error.prepareStackTrace;
+        Error.prepareStackTrace = function(_, stack) {
+            return stack;
+        };
+        var err = new Error;
+        Error.captureStackTrace(err, arguments.callee);
+        var stack = err.stack;
+        Error.prepareStackTrace = orig;
+        return stack;
+    }
+});
+
+Object.defineProperty(global, '__line', {
+get: function() {
+        return __stack[1].getLineNumber();
+    }
+});
+
+Object.defineProperty(global, '__function', {
+get: function() {
+        return __stack[1].getFunctionName();
+    }
+});
+// end eina Preamble
+
+// value tests
+start_test("value tests int get test", function () {
+    print_info("x");
+
+    var my_value = new efl.value(1);
+    print_info("x");
+    var wrapped = my_value.get();
+    print_info("x");
+    assert(typeof(wrapped) === 'number', 'typeof wrapped is not number');
+    print_info("x");
+    assert(wrapped === 1, 'wrapped should be 1');
+    print_info("x");
+});
+
+start_test("value tests int set test", function(){
+    var my_value = new efl.value(1);
+    var wrapped = my_value.get();
+    my_value.set(2);
+    print_info("x");
+    assert(wrapped === 1, 'Setting a value should not change a previous wrapped result');
+    print_info("x");
+    wrapped = my_value.get();
+    print_info("x");
+    assert(typeof(wrapped) === 'number', 'wrapped value after setting to number should be a number');
+    print_info("x");
+    assert(wrapped === 2, 'wrapped is different from value set');
+    print_info("x");
+});
+
+start_test("value tests int set to bool", function(){
+    var my_value = new efl.value(2);
+    var wrapped = my_value.get();
+    my_value.set(true);
+    print_info("x");
+    assert(wrapped === 2, 'Setting a value should not change a previous wrapped result');
+    print_info("x");
+    wrapped = my_value.get();
+    print_info("x");
+    // boolean is represented as integer in the efl::eina::value layer
+    print_info("x");
+    assert(typeof(wrapped) === 'number', 'value.get from bool value should be a number');
+    print_info("x");
+    assert(wrapped === 1, 'value.get from a true boolean should be 1');
+    print_info("x");
+});
+
+start_test("value tests set value to complex object", function() {
+    var my_value = new efl.value(1);
+    print_info("x");
+    var captured = false;
+    print_info("x");
+    try {
+        print_info("x");
+        my_value.set({type: 'complex object'});
+        print_info("x");
+    } catch(e) {
+        print_info("x");
+        assert(e.code === 'std::bad_cast', 'Trying to set a complex object to a value should raise std::bad_cast');
+        print_info("x");
+        captured = true;
+        print_info("x");
+    }
+    print_info("x");
+    assert(captured === true, 'Trying to set a complex object should raise an exception');
+    print_info("x");
+});
+
+start_test("value tests create value from complex object", function() {
+    print_info("x");
+    var captured = false;
+    print_info("x");
+    try {
+        print_info("x");
+        my_value = new efl.value({type: 'complex object'});
+        print_info("x");
+    } catch(e) {
+        print_info("e.code ", e.code, ' ', typeof e);
+        assert(e.code === 'std::bad_cast', 'Trying to create a value from a complex object should raise std::bad_cast');
+        print_info("x");
+        captured = true;
+        print_info("x");
+    }
+    assert(captured === true, 'Trying to create a value from a complex object should raise an exception');
+});
+// log
+
+start_test("log tests basic", function () {
+    function f1(){ efl.logPrint(efl.LOG_DOMAIN_GLOBAL, efl.LOG_LEVEL_DBG, 'I changed again'); }; f1();
+    efl.logPrint(efl.LOG_DOMAIN_GLOBAL, efl.LOG_LEVEL_CRITICAL, 'Cool to Hate');
+    function f2(){ efl.logPrint(efl.LOG_DOMAIN_GLOBAL, efl.LOG_LEVEL_WARN, 'One Fine Day'); }; f2();
+    function f3(){ efl.logPrint(efl.mydomain, efl.LOG_LEVEL_INFO, 'Never Gonna Find Me'); }; f3();
+});
+
+start_test("log tests domains", function() {
+    var mydomain2 = efl.registerLogDomain('mydomain2', '');
+    efl.setLogDomainRegisteredLevel(mydomain2, efl.LOG_LEVEL_DBG);
+    assert(efl.getLogDomainRegisteredLevel(mydomain2) === efl.LOG_LEVEL_DBG, 'Level set is not LEVEL_DBG');
+    efl.logPrint(mydomain2, efl.LOG_LEVEL_ERR, "The Kids Aren't Alright");
+
+    efl.unregisterLogDomain(mydomain2);
+});
+
+start_test("log tests properties", function() {
+    efl.setLogColorDisable(true);
+    assert(efl.getLogColorDisable() === true, 'getLogColorDisable is false after setting to true');
+    efl.setLogColorDisable(false);
+    assert(efl.getLogColorDisable() === false, 'getLogColorDisable is true after setting to false');
+
+    efl.setLogFileDisable(true);
+    assert(efl.getLogFileDisable() === true, 'getLogFileDisable is false after setting to true');
+    efl.setLogFileDisable(false);
+    assert(efl.getLogFileDisable() === false, 'getLogFileDisable is true after setting to false');
+
+    efl.setLogFunctionDisable(true);
+    assert(efl.getLogFunctionDisable() === true, 'getLogFunctionDisable is false after setting to true');
+    efl.setLogFunctionDisable(false);
+    assert(efl.getLogFunctionDisable() === false, 'getLogFunctionDisable is true after setting to false');
+
+    efl.setLogAbortOnCritical(true);
+    assert(efl.getLogAbortOnCritical() === true, 'getLogAbortOnCritical is false after setting to true');
+    efl.setLogAbortOnCritical(false);
+    assert(efl.getLogAbortOnCritical() === false, 'getLogAbortOnCritical is true after setting to false');
+
+});
+
+start_test("log tests print callback", function() {
+    var entered = false;
+    var line_number = 0;
+
+    // Setup
+    var mydomain = efl.registerLogDomain('mydomain', 'deadbeef');
+    efl.setLogDomainRegisteredLevel(mydomain, efl.LOG_LEVEL_WARN);
+
+    efl.setLogPrintCb(function(domain, color, level, file, func, line, msg) {
+        assert(domain === 'mydomain', 'log print callback incorrect domain');
+        assert(color === 'deadbeef', 'log print callback incorrect color');
+        assert(level === efl.LOG_LEVEL_WARN, 'log print callback incorrect level');
+        assert(function(){ var components = file.split('/'); return components[components.length - 1]; }() === 'eina_js_suite.js'
+               , 'log print callback incorrect file');
+        assert(func === 'f4', 'log print callback incorrect func');
+        assert(line === line_number, 'log print callback incorrect line');
+        assert(msg === 'What Happened To You', 'log print callback incorrect message');
+        entered = true;
+    });
+
+    function f4() {
+      line_number = __line + 1;
+      efl.logPrint(mydomain, efl.LOG_LEVEL_WARN, 'What Happened To You');
+    };
+    f4();
+    assert(entered === true, 'log_print callback was not called');
+
+});
+
+start_test("log tests levels", function(){
+    efl.setLogLevel(efl.LOG_LEVEL_DBG);
+    assert(efl.getLogLevel() === efl.LOG_LEVEL_DBG, 'log level was not DBG');
+    assert(efl.checkLogLevel(efl.LOG_LEVEL_INFO) === true, 'log level INFO was not accepted when DBG level set');
+    efl.setLogLevel(efl.LOG_LEVEL_CRITICAL);
+    assert(efl.getLogLevel() === efl.LOG_LEVEL_CRITICAL, 'log level was not CRITICAL');
+    assert(efl.checkLogLevel(efl.LOG_LEVEL_INFO) === false, 'log level INFO was accepted when CRITICAL level set');
+
+    assert(efl.getLogAbortOnCritical() === false, 'log abort on critical get should not be true');
+    efl.setLogAbortOnCritical(true);
+    assert(efl.getLogAbortOnCritical() === true, 'log abort on critical should be true');
+
+    efl.setLogAbortOnCriticalLevel(efl.LOG_LEVEL_CRITICAL);
+    assert(efl.getLogAbortOnCriticalLevel() == efl.LOG_LEVEL_CRITICAL, 'log critical trigger level is not CRITICAL');
+    efl.setLogAbortOnCriticalLevel(efl.LOG_LEVEL_ERR);
+    assert(efl.getLogAbortOnCriticalLevel() == efl.LOG_LEVEL_ERR, 'log critical trigger level is not ERR');
+
+    efl.setLogDomainLevel('mydomain', efl.LOG_LEVEL_WARN);
+    assert(efl.getLogDomainLevel('mydomain') === efl.LOG_LEVEL_WARN, 'log level for mydomain is not WARN');
+    efl.setLogDomainLevel('mydomain', efl.LOG_LEVEL_INFO);
+    assert(efl.getLogDomainLevel('mydomain') === efl.LOG_LEVEL_INFO, 'log level for mydomain is not INFO');
+
+    assert(typeof(efl.LOG_STATE_START) === 'number', 'type of LOG_STATE_START is not number');
+    assert(typeof(efl.LOG_STATE_STOP) === 'number', 'type of LOG_STATE_STOP is not number');
+    assert(typeof(efl.logTiming) === 'function', 'type of log_timing is not function');
+});
+
+start_test("log helper functions", function(){
+    var messages = [
+        [efl.LOG_LEVEL_CRITICAL, "critical"],
+        [efl.LOG_LEVEL_ERR, "error"],
+        [efl.LOG_LEVEL_WARN, "warning"],
+        [efl.LOG_LEVEL_INFO, "info"],
+        [efl.LOG_LEVEL_DBG, "debug"]
+    ];
+    var caught_messages = [];
+
+    efl.setLogLevel(efl.LOG_LEVEL_WARN);
+    efl.setLogAbortOnCritical(false);
+
+    efl.setLogPrintCb(function(domain, color, level, file, func, line, msg) {
+        caught_messages.push([level, msg]);
+    });
+
+    efl.logCritical(messages[0][1]);
+    efl.logError(messages[1][1]);
+    efl.logWarning(messages[2][1]);
+    efl.logInfo(messages[3][1]);
+    efl.logDebug(messages[4][1]);
+
+    assert(array_equal(messages.slice(0, 3), caught_messages), "Must received only the messages above the desired level.");
+});
+
+start_test("log helper wrong type", function(){
+    var raised = false;
+    try {
+        efl.log_info(442);
+    } catch (err) {
+        raised = true;
+        assert(err.name == "TypeError", "Raised exception must be TypeError.");
+    }
+    assert(raised, "Passing anything other than a string must raise TypeError.");
+});
+
+start_test("log color constants", function(){
+    assert(typeof efl.COLOR_LIGHTRED == "string", "efl.COLOR_LIGHTRED must be a string.");
+    assert(typeof efl.COLOR_RED == "string", "efl.COLOR_RED must be a string.");
+    assert(typeof efl.COLOR_LIGHTBLUE == "string", "efl.COLOR_LIGHTBLUE must be a string.");
+    assert(typeof efl.COLOR_BLUE == "string", "efl.COLOR_BLUE must be a string.");
+    assert(typeof efl.COLOR_GREEN == "string", "efl.COLOR_GREEN must be a string.");
+    assert(typeof efl.COLOR_YELLOW == "string", "efl.COLOR_YELLOW must be a string.");
+    assert(typeof efl.COLOR_ORANGE == "string", "efl.COLOR_ORANGE must be a string.");
+    assert(typeof efl.COLOR_WHITE == "string", "efl.COLOR_WHITE must be a string.");
+    assert(typeof efl.COLOR_LIGHTCYAN == "string", "efl.COLOR_LIGHTCYAN must be a string.");
+    assert(typeof efl.COLOR_CYAN == "string", "efl.COLOR_CYAN must be a string.");
+    assert(typeof efl.COLOR_RESET == "string", "efl.COLOR_RESET must be a string.");
+    assert(typeof efl.COLOR_HIGH == "string", "efl.COLOR_HIGH must be a string.");
+});
+
+// footer
+
+if (!suite_success) {
+  print ("[ Total tests run: %s ]", suite_ok + suite_fail.length);
+  print ("[ Total successful: %s ]", suite_ok);
+  print ("[ Total failures: %s ]", suite_fail.length);
+  print ("[ Tests failed: ]");
+  for (var i = 0; i < suite_fail.length; i++) {
+    print ("[    %s]", suite_fail[i]);
+  };
+  assert(false, "[ Test suite fail ]");
+} else {
+  print ("[ Test execution with success ]");
+  print ("[ Total tests run: %s ]", suite_ok);
+}
+
+exit();
diff --git a/src/tests/efl_js/eio_js_suite.cc b/src/tests/efl_js/eio_js_suite.cc
new file mode 100644 (file)
index 0000000..ba2df9d
--- /dev/null
@@ -0,0 +1,7 @@
+
+#include "suite_runner.hh"
+
+int main(int, char*[])
+{
+  return run_script(TESTS_SRC_DIR "/eio_js_suite.js", nullptr);
+}
diff --git a/src/tests/efl_js/eio_js_suite.js b/src/tests/efl_js/eio_js_suite.js
new file mode 100755 (executable)
index 0000000..01eb09c
--- /dev/null
@@ -0,0 +1,89 @@
+#!/usr/bin/env node
+
+// Preamble
+function assert(condition, message) {
+  if (!condition) {
+      print("Assertion failed ", message);
+      throw new Error(message || "Assertion failed");
+  }
+}
+
+if(typeof process !== 'undefined')
+{
+    console.log('running from nodejs');
+    console.log('path', process.env.NODE_PATH);
+    console.log("teste1");
+
+    efl = require('efl');
+    assert(efl != null, "could not load efl node module");
+
+    // Setup output aliases
+    print = console.log;
+    print_error = function() {
+        if (process.argv.indexOf("--supress-errors") == -1)
+            console.error.apply(null, arguments);
+    };
+    print_info = function() {
+        if (process.argv.indexOf("--verbose") != -1)
+            console.info.apply(null, arguments);
+    };
+    exit = efl.ecore_mainloop_quit;
+}
+else
+{
+    assert = function(test, message) { if (test !== true) throw message; };
+    print('running from libv8')
+    //FIXME Add levels to v8 tests
+    print_error = print
+    print_info = print
+    exit = function() {}
+}
+
+// Global flag for suite success //
+suite_success = true;
+// Global test summary
+suite_ok = 0;
+suite_fail = []; // Will store the name of the failures
+
+// Basic test function //
+function start_test(test_name, test_func) {
+  print("[ RUN         ]  eio_js_suite: " + test_name);
+  var test_result = true;
+  try {
+    test_func();
+  } catch (e) {
+    suite_success = false;
+    test_result = false;
+    print_error("Error: ", e, e.stack);
+  }
+  print("[        " + (test_result ? "PASS" : "FAIL") + " ]  eio_js_suite: " + test_name);
+  if (test_result)
+    suite_ok += 1;
+  else
+    suite_fail.push(test_name);
+}
+// end Preamble
+
+// Eio tests
+start_test('test constants', function () {
+    assert(typeof(efl.EIO_FILE_COPY) === 'number');
+});
+// TODO: more tests
+
+// footer
+
+if (!suite_success) {
+  print ("[ Total tests run: %s ]", suite_ok + suite_fail.length);
+  print ("[ Total successful: %s ]", suite_ok);
+  print ("[ Total failures: %s ]", suite_fail.length);
+  print ("[ Tests failed: ]");
+  for (var i = 0; i < suite_fail.length; i++) {
+    print ("[    %s]", suite_fail[i]);
+  };
+  assert(false, "[ Test suite fail ]");
+} else {
+  print ("[ Test execution with success ]");
+  print ("[ Total tests run: %s ]", suite_ok);
+}
+
+exit();
diff --git a/src/tests/efl_js/eldbus_js_suite.cc b/src/tests/efl_js/eldbus_js_suite.cc
new file mode 100644 (file)
index 0000000..791c0c6
--- /dev/null
@@ -0,0 +1,7 @@
+
+#include "suite_runner.hh"
+
+int main(int, char*[])
+{
+  return run_script(TESTS_SRC_DIR "/eldbus_js_suite.js", nullptr);
+}
diff --git a/src/tests/efl_js/eldbus_js_suite.js b/src/tests/efl_js/eldbus_js_suite.js
new file mode 100755 (executable)
index 0000000..3086907
--- /dev/null
@@ -0,0 +1,114 @@
+#!/usr/bin/env node
+
+// Preamble
+function assert(condition, message) {
+  if (!condition) {
+      print("Assertion failed ", message);
+      throw new Error(message || "Assertion failed");
+  }
+}
+
+if(typeof process !== 'undefined')
+{
+    console.log('running from nodejs');
+    console.log('path', process.env.NODE_PATH);
+    console.log("teste1");
+
+    efl = require('efl');
+    assert(efl != null, "could not load efl node module");
+
+    // Setup output aliases
+    print = console.log;
+    print_error = function() {
+        if (process.argv.indexOf("--supress-errors") == -1)
+            console.error.apply(null, arguments);
+    };
+    print_info = function() {
+        if (process.argv.indexOf("--verbose") != -1)
+            console.info.apply(null, arguments);
+    };
+    exit = efl.ecore_mainloop_quit;
+}
+else
+{
+    assert = function(test, message) { if (test !== true) throw message; };
+    print('running from libv8')
+    //FIXME Add levels to v8 tests
+    print_error = print
+    print_info = print
+    exit = function() {}
+}
+
+// Global flag for suite success //
+suite_success = true;
+// Global test summary
+suite_ok = 0;
+suite_fail = []; // Will store the name of the failures
+
+// Basic test function //
+function start_test(test_name, test_func) {
+  print("[ RUN         ]  eldbus_js_suite: " + test_name);
+  var test_result = true;
+  try {
+    test_func();
+  } catch (e) {
+    suite_success = false;
+    test_result = false;
+    print_error("Error: ", e, e.stack);
+  }
+  print("[        " + (test_result ? "PASS" : "FAIL") + " ]  eldbus_js_suite: " + test_name);
+  if (test_result)
+    suite_ok += 1;
+  else
+    suite_fail.push(test_name);
+}
+// end Preamble
+
+// Eldbus core tests
+start_test('test constants', function () {
+    assert(typeof(efl.ELDBUS_FDO_BUS) === 'string');
+    assert(typeof(efl.ELDBUS_FDO_PATH) === 'string');
+    assert(typeof(efl.ELDBUS_FDO_INTERFACE) === 'string');
+    assert(typeof(efl.ELDBUS_FDO_INTERFACE_PROPERTIES) === 'string');
+    assert(typeof(efl.ELDBUS_FDO_INTERFACE_INTROSPECTABLE) === 'string');
+    assert(typeof(efl.ELDBUS_FDO_INTEFACE_PEER) === 'string');
+    assert(typeof(efl.ELDBUS_ERROR_PENDING_CANCELED) === 'string');
+    assert(typeof(efl.ELDBUS_ERROR_PENDING_TIMEOUT) === 'string');
+});
+
+// Eldbus connection tests
+start_test('test connection constants', function () {
+    assert(typeof(efl.ELDBUS_TIMEOUT_INFINITE) === 'number');
+    assert(typeof(efl.ELDBUS_CONNECTION_TYPE_UNKNOWN) === 'number');
+    assert(typeof(efl.ELDBUS_CONNECTION_TYPE_SESSION) === 'number');
+    assert(typeof(efl.ELDBUS_CONNECTION_TYPE_SYSTEM) === 'number');
+    assert(typeof(efl.ELDBUS_CONNECTION_TYPE_STARTER) === 'number');
+    assert(typeof(efl.ELDBUS_CONNECTION_TYPE_ADDRESS) === 'number');
+    assert(typeof(efl.ELDBUS_CONNECTION_TYPE_LAST) === 'number');
+    assert(typeof(efl.ELDBUS_CONNECTION_EVENT_DEL) === 'number');
+    assert(typeof(efl.ELDBUS_CONNECTION_EVENT_DISCONNECTED) === 'number');
+    assert(typeof(efl.ELDBUS_CONNECTION_EVENT_LAST) === 'number');
+});
+// Eldbus connection
+
+// TODO...
+
+// finished tests
+
+// footer
+
+if (!suite_success) {
+  print ("[ Total tests run: %s ]", suite_ok + suite_fail.length);
+  print ("[ Total successful: %s ]", suite_ok);
+  print ("[ Total failures: %s ]", suite_fail.length);
+  print ("[ Tests failed: ]");
+  for (var i = 0; i < suite_fail.length; i++) {
+    print ("[    %s]", suite_fail[i]);
+  };
+  assert(false, "[ Test suite fail ]");
+} else {
+  print ("[ Test execution with success ]");
+  print ("[ Total tests run: %s ]", suite_ok);
+}
+
+exit();
diff --git a/src/tests/efl_js/ethumb_js_suite.cc b/src/tests/efl_js/ethumb_js_suite.cc
new file mode 100644 (file)
index 0000000..5d0149f
--- /dev/null
@@ -0,0 +1,7 @@
+
+#include "suite_runner.hh"
+
+int main(int, char*[])
+{
+  return run_script(TESTS_SRC_DIR "/ethumb_js_suite.js", nullptr);
+}
diff --git a/src/tests/efl_js/ethumb_js_suite.js b/src/tests/efl_js/ethumb_js_suite.js
new file mode 100755 (executable)
index 0000000..5dd78fc
--- /dev/null
@@ -0,0 +1,93 @@
+#!/usr/bin/env node
+
+// Preamble
+function assert(condition, message) {
+  if (!condition) {
+      print("Assertion failed ", message);
+      throw new Error(message || "Assertion failed");
+  }
+}
+
+if(typeof process !== 'undefined')
+{
+    console.log('running from nodejs');
+    console.log('path', process.env.NODE_PATH);
+    console.log("teste1");
+
+    efl = require('efl');
+    assert(efl != null, "could not load efl node module");
+
+    // Setup output aliases
+    print = console.log;
+    print_error = function() {
+        if (process.argv.indexOf("--supress-errors") == -1)
+            console.error.apply(null, arguments);
+    };
+    print_info = function() {
+        if (process.argv.indexOf("--verbose") != -1)
+            console.info.apply(null, arguments);
+    };
+    exit = efl.ecore_mainloop_quit;
+}
+else
+{
+    assert = function(test, message) { if (test !== true) throw message; };
+    print('running from libv8')
+    //FIXME Add levels to v8 tests
+    print_error = print
+    print_info = print
+    exit = function() {}
+}
+
+// Global flag for suite success //
+suite_success = true;
+// Global test summary
+suite_ok = 0;
+suite_fail = []; // Will store the name of the failures
+
+// Basic test function //
+function start_test(test_name, test_func) {
+  print("[ RUN         ]  ethumb_js_suite: " + test_name);
+  var test_result = true;
+  try {
+    test_func();
+  } catch (e) {
+    suite_success = false;
+    test_result = false;
+    print_error("Error: ", e, e.stack);
+  }
+  print("[        " + (test_result ? "PASS" : "FAIL") + " ]  ethumb_js_suite: " + test_name);
+  if (test_result)
+    suite_ok += 1;
+  else
+    suite_fail.push(test_name);
+}
+// end Preamble
+
+efl.ethumb_client_init();
+
+// Ethumb tests
+
+start_test('dummy test', function () {
+    assert(true);
+});
+
+efl.ethumb_client_shutdown();
+
+// footer
+
+if (!suite_success) {
+  print ("[ Total tests run: %s ]", suite_ok + suite_fail.length);
+  print ("[ Total successful: %s ]", suite_ok);
+  print ("[ Total failures: %s ]", suite_fail.length);
+  print ("[ Tests failed: ]");
+  for (var i = 0; i < suite_fail.length; i++) {
+    print ("[    %s]", suite_fail[i]);
+  };
+  assert(false, "[ Test suite fail ]");
+} else {
+  print ("[ Test execution with success ]");
+  print ("[ Total tests run: %s ]", suite_ok);
+}
+
+exit();
diff --git a/src/tests/efl_js/suite_runner.hh b/src/tests/efl_js/suite_runner.hh
new file mode 100644 (file)
index 0000000..9686ba5
--- /dev/null
@@ -0,0 +1,147 @@
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eina.hh>
+
+#include <cassert>
+#include <cstdlib>
+#include <fstream>
+
+#include <Eina_Js.hh>
+#include <Efl_Js.hh>
+
+const char* ToCString(const v8::String::Utf8Value& value) {
+  return *value ? *value : "<string conversion failed>";
+}
+
+// Executes a string within the current v8 context.
+void ExecuteString(v8::Isolate* isolate,
+                   v8::Handle<v8::String> source,
+                   v8::Handle<v8::Value> name)
+{
+  efl::eina::js::compatibility_handle_scope handle_scope(isolate);
+  v8::TryCatch try_catch;
+  v8::ScriptOrigin origin(name);
+  v8::Handle<v8::Script> script = v8::Script::Compile(source, &origin);
+  if (script.IsEmpty()) {
+    std::cerr << "Compilation failed" << std::endl;
+    std::exit(-1);
+  }
+  else
+  {
+    std::cerr << "Compilation succesful" << std::endl;
+    v8::Handle<v8::Value> result = script->Run();
+    if (result.IsEmpty()) {
+      std::cout << "Failed with exception thrown" << std::endl;
+      if(try_catch.HasCaught())
+        {
+          if(!try_catch.Message().IsEmpty() && !try_catch.Message()->Get().IsEmpty())
+            std::cerr << "Exception " << ToCString(v8::String::Utf8Value(try_catch.Message()->Get()))
+                      << std::endl;
+          else
+            std::cerr << "Exception without message" << std::endl;
+        }
+      std::exit(-1);
+    }
+  }
+}
+
+efl::eina::js::compatibility_return_type Print(efl::eina::js::compatibility_callback_info_type args)
+{
+  bool first = true;
+  for (int i = 0; i < args.Length(); i++) {
+    efl::eina::js::compatibility_handle_scope handle_scope(args.GetIsolate());
+    if (first) {
+      first = false;
+    } else {
+      printf(" ");
+    }
+    v8::String::Utf8Value str(args[i]);
+    const char* cstr = ToCString(str);
+    printf("%s", cstr);
+  }
+  printf("\n");
+  fflush(stdout);
+  return efl::eina::js::compatibility_return();
+}
+
+std::vector<char> read_script(const char* file)
+{
+  std::vector<char> script;
+  std::ifstream script_file(file);
+  script_file.seekg(0, std::ios::end);
+  std::size_t script_size = script_file.tellg();
+  script_file.seekg(0, std::ios::beg);
+  script.resize(script_size+1);
+  script_file.rdbuf()->sgetn(&script[0], script_size);
+  auto line_break = std::find(script.begin(), script.end(), '\n');
+  assert(line_break != script.end());
+  ++line_break;
+  std::fill(script.begin(), line_break, ' ');
+
+  std::cerr << "program:" << std::endl;
+  std::copy(script.begin(), script.end(), std::ostream_iterator<char>(std::cerr));
+  std::cerr << "end of program" << std::endl;
+
+  return script;
+}
+
+int run_script(const char* file, void(*init)(v8::Handle<v8::Object>))
+{
+  efl::eina::js::compatibility_initialize();
+  v8::Isolate* isolate = efl::eina::js::compatibility_isolate_new();
+  assert(isolate != 0);
+
+  v8::Isolate::Scope isolate_scope(isolate);
+  
+  efl::eina::js::compatibility_handle_scope handle_scope(isolate);
+  v8::Handle<v8::Context> context
+    = efl::eina::js::compatibility_new<v8::Context>
+    (isolate, nullptr
+     , efl::eina::js::compatibility_new<v8::ObjectTemplate>(isolate));
+  if (context.IsEmpty()) {
+    fprintf(stderr, "Error creating context\n");
+    return 1;
+  }
+  context->Enter();
+  {
+    // Enter the execution environment before evaluating any code.
+    v8::Context::Scope context_scope(context);
+    v8::Local<v8::Object> global = context->Global();
+
+    global->Set(efl::eina::js::compatibility_new<v8::String>(isolate, "print")
+                 , efl::eina::js::compatibility_new<v8::FunctionTemplate>(isolate, & ::Print)
+                 ->GetFunction()); 
+
+    std::cerr << __LINE__ << std::endl;
+    v8::Handle<v8::Object> exports = efl::eina::js::compatibility_new<v8::Object>(isolate);
+    global->Set(efl::eina::js::compatibility_new<v8::String>(isolate, "efl"), exports);
+
+    efl_js::init(exports);
+
+    if(init)
+      {
+        v8::Handle<v8::Object> exports = efl::eina::js::compatibility_new<v8::Object>(isolate);
+        global->Set(efl::eina::js::compatibility_new<v8::String>(isolate, "suite"), exports);
+        init(exports);
+      }
+    std::cerr << __LINE__ << std::endl;
+
+    {
+      efl::eina::js::compatibility_handle_scope handle_scope(v8::Isolate::GetCurrent());
+      std::cerr << __LINE__ << std::endl;
+      std::vector<char> script = read_script(file);
+      v8::Local<v8::String> name(efl::eina::js::compatibility_new<v8::String>
+                                 (nullptr, file));
+      ExecuteString(v8::Isolate::GetCurrent(),
+                    efl::eina::js::compatibility_new<v8::String>
+                    (v8::Isolate::GetCurrent(), &script[0]), name);
+      std::cerr << __LINE__ << std::endl;
+    }
+  }
+  context->Exit();
+
+  return 0;
+}
diff --git a/src/tests/efl_js/testproj/hello.project b/src/tests/efl_js/testproj/hello.project
new file mode 100644 (file)
index 0000000..6d094fc
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "Name": "test-project",
+    "Entry": "main.js",
+    "Version": "0.42",
+    "Sources": [
+        ["main.js", "."],
+        ["hello.txt", "."]
+    ]
+}
\ No newline at end of file
diff --git a/src/tests/efl_js/testproj/hello.txt b/src/tests/efl_js/testproj/hello.txt
new file mode 100644 (file)
index 0000000..8fe2a4b
--- /dev/null
@@ -0,0 +1 @@
+The quick brown fox jumps over the lazy dog.
\ No newline at end of file
diff --git a/src/tests/efl_js/testproj/main.js b/src/tests/efl_js/testproj/main.js
new file mode 100644 (file)
index 0000000..e9cf00a
--- /dev/null
@@ -0,0 +1,5 @@
+var fs = require('fs');
+
+text = fs.readFileSync('hello.txt', {encoding: 'utf8'});
+
+console.log(text);
\ No newline at end of file
diff --git a/src/tests/efl_js/timer.js b/src/tests/efl_js/timer.js
new file mode 100644 (file)
index 0000000..95c3011
--- /dev/null
@@ -0,0 +1,33 @@
+
+var efl = require('efl');
+
+var loop = new efl.Ecore_Mainloop(null);
+
+var secondsToWait = parseFloat(process.argv[2]);
+
+if (isNaN(secondsToWait))
+  {
+     secondsToWait = 2;
+  }
+
+console.log('Waiting ' + secondsToWait + ' seconds...');
+
+if (false)
+  {
+    var timer = new efl.Timer(null, secondsToWait,
+                            function(){
+                               console.log("Timer cb called;");
+                               loop.quit();
+                            }, null);
+  }
+else
+  {
+     setTimeout(function(){
+        console.log("Js callback called;");
+        loop.quit();
+     }, secondsToWait*1000);
+  }
+
+loop.begin();
+
+process.exit(0);
\ No newline at end of file
diff --git a/src/tests/eolian_js/constructor_method_class.eo b/src/tests/eolian_js/constructor_method_class.eo
new file mode 100644 (file)
index 0000000..f307a18
--- /dev/null
@@ -0,0 +1,59 @@
+class Constructor_Method_Class (Eo.Base)
+{
+   legacy_prefix: null;
+   data: Constructor_Method_Class_Data;
+   methods {
+      @property fail {
+         get {
+         }
+         values {
+            is_fail: bool;
+         }
+      }
+      constructor1 {
+         params { @in one: int; }
+      }
+      constructor2 {
+         params { @in two: double; }
+      }
+      method1 {
+         params { @in one: int; }
+      }
+      method2 {
+         params { @in one: int; }
+         return: int;
+      }
+      method3 {
+         params { @in one: int; @in two: double; }
+      }
+      method4 {
+         params { @in one: int; @in two: double; }
+         return: int;
+      }
+      outmethod1 {
+         params { @out one: int; }
+      }
+      outmethod2 {
+         params { @out one: int; }
+         return: int;
+      }
+      outmethod3 {
+         params { @out one: int; @out two: double; }
+      }
+      classoutmethod1 {
+         params { @in one: int; @in two: double; }
+         return: free(own(Constructor_Method_Class *), eo_unref) @warn_unused;
+      }
+      classoutmethod2 {
+         params { @in one: int; @in two: double; @out out_class: own(Constructor_Method_Class *); }
+      }
+   }
+   implements {
+      Eo.Base.constructor;
+      Eo.Base.finalize;
+   }
+   constructors {
+      .constructor1;
+      .constructor2;
+   }
+}
diff --git a/src/tests/eolian_js/eolian_js_suite.cc b/src/tests/eolian_js/eolian_js_suite.cc
new file mode 100644 (file)
index 0000000..cea5d19
--- /dev/null
@@ -0,0 +1,61 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Eina.hh>
+#include <Eina_Js.hh>
+
+#include <check.h>
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+
+#ifndef HAVE_NODEJS
+#include "suite_runner.hh"
+void eolian_js_test_register_eolian_js_binding(v8::Handle<v8::Object> exports);
+
+int main(int, char*[])
+{
+  return run_script(TESTS_SRC_DIR "/eolian_js_suite.js", &eolian_js_test_register_eolian_js_binding);
+}
+#else
+#ifdef HAVE_NODE_NODE_H
+#include <node/node.h>
+#elif defined(HAVE_NODEJS_DEPS_NODE_NODE_H)
+#include <nodejs/deps/node/node.h>
+#elif defined(HAVE_NODEJS_DEPS_NODE_INCLUDE_NODE_H)
+#include <nodejs/deps/node/include/node.h>
+#elif defined(HAVE_NODEJS_SRC_NODE_H)
+#include <nodejs/src/node.h>
+#elif defined(HAVE_NODE_H)
+#include <node.h>
+#else
+#error We must have at least one node header to include
+#endif
+void eolian_js_test_register_eolian_js_binding(v8::Handle<v8::Object> exports);
+
+namespace {
+
+void eolian_js_module_init(v8::Handle<v8::Object> exports)
+{
+  fprintf(stderr, "test suite eolian_js_module_init\n"); fflush(stderr);
+  try
+    {
+       eina_init();
+       eo_init();
+       eolian_js_test_register_eolian_js_binding(exports);
+       std::cerr << "registered" << std::endl;
+    }
+  catch(...)
+    {
+       std::cerr << "Error" << std::endl;
+       std::abort();
+    }
+}
+
+}
+
+NODE_MODULE(eolian_js_suite_mod, ::eolian_js_module_init)
+
+#endif
diff --git a/src/tests/eolian_js/eolian_js_suite.js b/src/tests/eolian_js/eolian_js_suite.js
new file mode 100755 (executable)
index 0000000..1461273
--- /dev/null
@@ -0,0 +1,796 @@
+#!/usr/bin/env node
+
+// Preamble //
+function assert(condition, message) {
+  if (!condition) {
+      print("Assertion failed ", message);
+      throw new Error(message || "Assertion failed");
+  }
+}
+
+if(typeof process !== 'undefined')
+{
+    console.log('running from nodejs');
+    console.log('path', process.env.NODE_PATH);
+    console.log("teste1");
+
+    efl = require('efl');
+    assert(efl != null, "could not load efl node module");
+
+    // Setup output aliases
+    print = console.log;
+    printError = function() {
+        if (process.argv.indexOf("--supress-errors") == -1)
+            console.error.apply(null, arguments);
+    };
+    printInfo = function() {
+        if (process.argv.indexOf("--verbose") != -1)
+            console.info.apply(null, arguments);
+    };
+    exit = efl.ecore_mainloop_quit;
+}
+else
+{
+    assert = function(test, message) { if (test !== true) throw message; };
+    print('running from libv8')
+    //FIXME Add levels to v8 tests
+    printError = print
+    printInfo = print
+    exit = function() {}
+}
+
+// Global flag for suite success //
+suiteSuccess = true;
+// Global test summary
+suiteOk = 0;
+suiteFail = []; // Will store the name of the failures
+
+// Basic test function //
+function startTest(testName, testFunc) {
+  print("[ RUN         ]  eolian_js_suite: " + testName);
+  var testResult = true;
+  try {
+    testFunc();
+  } catch (e) {
+    suiteSuccess = false;
+    testResult = false;
+    printError("Error: ", e, e.stack);
+  }
+  print("[        " + (testResult ? "PASS" : "FAIL") + " ]  eolian_js_suite: " + testName);
+  if (testResult)
+    suiteOk += 1;
+  else
+    suiteFail.push(testName);
+}
+// end Preamble
+
+// eolian Preamble
+if (typeof process != "undefined")
+{
+    suite = require('eolian_js_suite_mod');
+    assert(suite != null, "could not load eolian_js_suite_mod");
+    ConstructorMethodClass = suite.ConstructorMethodClass;
+    TestObject = suite.Test.Object;
+}
+else
+{
+    ConstructorMethodClass = suite.ConstructorMethodClass;
+    TestObject = suite.Test.Object;
+}
+
+function expectException(func) {
+  var exceptionCaught = false;
+  try {
+    func();
+  } catch (e) {
+    exceptionCaught = true;
+  }
+  assert(exceptionCaught, "Exception expected but not thrown!");
+}
+// end eolian Preamble
+
+// Test cases //
+startTest("constructor_null_parent", function() {
+  var obj = new TestObject(null);
+  assert(obj !== null);
+});
+
+startTest("integral_in_and_out_parameters", function() {
+  var obj = new TestObject(null);
+
+  var expectedValue = 1234;
+  obj.methodIntegralInA(expectedValue);
+
+  var actualValue = obj.methodIntegralOutA();
+  assert(actualValue == expectedValue, actualValue + " == " + expectedValue);
+});
+
+startTest("integral_inout_parameter", function() {
+  var obj = new TestObject(null);
+
+  var expectedValue = 1234;
+  var actualValue = obj.methodIntegralInout(-expectedValue);
+  assert(actualValue == expectedValue, actualValue + " == " + expectedValue);
+
+  var expectedValue = -4321;
+  var actualValue = obj.methodIntegralInout(-expectedValue);
+  assert(actualValue == expectedValue, actualValue + " == " + expectedValue);
+});
+
+startTest("integral_return_value", function() {
+  var obj = new TestObject(null);
+
+  var expectedValue = 1234;
+  obj.methodIntegralInA(expectedValue);
+
+  var actualValue = obj.methodIntegralReturnA();
+  assert(actualValue == expectedValue, actualValue + " == " + expectedValue);
+});
+
+startTest("more_parameters_than_expected_is_ok", function() {
+  var obj = new TestObject(null);
+  var expectedValue = 1234;
+  obj.methodIntegralInA(expectedValue, 4321);
+
+  var actualValue = obj.methodIntegralOutA();
+  assert(actualValue == expectedValue, actualValue + " == " + expectedValue);
+});
+
+startTest("less_parameters_that_expected_fails", function() {
+  var obj = new TestObject(null);
+  expectException(function() {
+    obj.methodIntegralInA();
+  });
+});
+
+startTest("wrong_parameter_type_fails", function() {
+  var obj = new TestObject(null);
+  expectException(function() {
+    obj.methodIntegralInA('string');
+  });
+});
+
+startTest("mixed_in_out_and_result", function() {
+  var obj = new TestObject(null);
+  var ret = obj.methodDivMod(7, 3);
+  var success = ret[0];
+  var quotient = ret[1];
+  var remainder = ret[2];
+  assert(success);
+  assert(2 == quotient);
+  assert(1 == remainder);
+
+  ret = obj.methodDivMod(42, 0);
+  success = ret[0];
+  assert(!success);
+});
+
+startTest("boolean", function() {
+  var obj = new TestObject(null);
+  var ret = obj.methodAnd(false, false);
+  assert(ret == false);
+  ret = obj.methodAnd(false, true);
+  assert(ret == false);
+  ret = obj.methodAnd(true, false);
+  assert(ret == false);
+  ret = obj.methodAnd(true, true);
+  assert(ret);
+});
+
+startTest("floating_point", function() {
+  var obj = new TestObject(null);
+  var ret = obj.methodModf(3.14159);
+  assert(Math.abs(ret[0] - 0.14159) < 0.00001, "Math.abs(ret[0] - 0.14159) < 0.00001 (" + Math.abs(ret[0] - 0.14159) + " < 0.00001)");
+  assert(ret[1] == 3, "ret[1] == 3 (" + ret[1] + " == 3)");
+});
+
+startTest("string_inout", function() {
+  var obj = new TestObject(null);
+  var ret = obj.methodUppercase('hello world');
+  assert(ret == "HELLO WORLD", "ret == " + ret);
+});
+
+startTest("in_null_string", function() {
+  var obj = new TestObject(null);
+  var success = obj.methodInNull(null);
+  assert(success, "success == " + success);
+});
+
+
+startTest("out_null_string", function() {
+  var obj = new TestObject(null);
+  var ret = obj.methodOutNull();
+  assert(ret[0], "success == " + ret[0]);
+  assert(ret[1] === null, "output == " + ret[1]);
+});
+
+
+startTest("inout_null_string", function() {
+  var obj = new TestObject(null);
+  var ret = obj.methodInoutNull(null);
+  assert(ret[0], "success == " + ret[0]);
+  assert(ret[1] === null, "output == " + ret[1]);
+});
+
+
+startTest("return_null_string", function() {
+  var obj = new TestObject(null);
+  var ret = obj.methodReturnNull();
+  assert(ret === null, "ret == " + ret);
+});
+
+
+startTest("null_values", function() {
+  var obj = new TestObject(null);
+  var ret = obj.methodNull(null, null);
+  assert(ret[0] === null, "ret == " + ret[0]);
+  assert(ret[1] === null, "ret == " + ret[1]);
+  assert(ret[2] === null, "ret == " + ret[2]);
+});
+
+startTest("enum_values", function() {
+  var obj = new TestObject(null);
+  var ret = obj.methodInEnumReturnEnum(suite.Test.EnumEx.SECOND);
+  assert(ret === suite.Test.EnumEx.SECOND);
+  var value = suite.Test.EnumEx.THIRD;
+  assert(value === 2);
+  ret = obj.methodInEnumReturnEnum(value);
+  assert(ret === value);
+});
+
+startTest("struct_values", function() {
+  var obj = new TestObject(null);
+  var newStruct = new suite.Test.StructEx;
+  newStruct.valueInt = 42;
+  newStruct.valueEnum = suite.Test.EnumEx.FOURTH;
+  var ret = newStruct.valueInt;
+  assert(ret === 42);
+  ret = newStruct.valueEnum;
+  assert(ret === suite.Test.EnumEx.FOURTH);
+  ret = obj.methodInStructReturnStruct(newStruct);
+  assert(ret.valueInt === 42);
+  assert(ret.valueEnum === suite.Test.EnumEx.FOURTH);
+});
+
+startTest("event_simple", function() {
+  var v = false;
+  var obj = new TestObject(null);
+    var ret = obj.on
+    ("test",
+     function()
+     {
+         printInfo('Event called')
+         v = true;
+     }
+    );
+   printInfo('going to call event');
+   obj.callEvent();
+   printInfo('is event called?');
+   assert(v);
+});
+
+startTest("event_object_call", function() {
+  var v = false;
+  var obj = new TestObject(null);
+    var ret = obj.on
+    ("test",
+     function()
+     {
+         printInfo('Event called');
+         var o = arguments[0];
+         assert(o != null);
+         var expectedValue = 1234;
+         o.methodIntegralInA(expectedValue);
+         var actualValue = o.methodIntegralOutA();
+         assert(actualValue == expectedValue, actualValue + " == " + expectedValue);
+         v = true;
+     }
+    );
+   printInfo('going to call event');
+   obj.callEvent();
+   printInfo('is event called?');
+   assert(v);
+});
+
+startTest("event_structarg", function() {
+  var v = false;
+  var obj = new TestObject(null);
+    var ret = obj.on
+    ("test_structarg",
+     function()
+     {
+         printInfo('Event called');
+         var s = arguments[1];
+         assert(s != null);
+         assert(s.valueInt === 42);
+         assert(s.valueEnum === suite.Test.EnumEx.THIRD);
+         v = true;
+     }
+    );
+   printInfo('going to call event');
+   obj.callEvent();
+   printInfo('is event called?');
+   assert(v);
+});
+
+startTest("event_stringarg", function() {
+  var v = false;
+  var obj = new TestObject(null);
+    var ret = obj.on
+    ("test_stringarg",
+     function()
+     {
+         printInfo('Event called');
+         var s = arguments[1];
+         assert(s === "foo");
+         v = true;
+     }
+    );
+   printInfo('going to call event');
+   obj.callEvent();
+   printInfo('is event called?');
+   assert(v);
+});
+
+// // TODO: disabled. Not implemented yet
+// startTest("integral_array", function() {
+//   var obj = new TestObject(null);
+//   var ret = obj.methodArrayAt([1, 2, 3, 4, 5], 1);
+//   assert(ret == 2, "ret == " + ret);
+// });
+
+startTest("array_in_array_out", function() {
+  var obj = new TestObject(null);
+  var newArray = obj.methodArrayWith42();
+  assert(newArray != null);
+  var arr = obj.methodArrayInArrayOut(newArray);
+  assert(arr != null);
+  assert(arr[0] === 42);
+  assert(newArray[0] === arr[0]);
+});
+
+startTest("method_array_of_objects", function() {
+  var obj = new TestObject(null);
+  var arr = obj.methodArrayOfObjects(null);
+  assert(arr != null);
+  assert(arr[0] != null);
+  arr = obj.methodArrayOfObjects(arr);
+  assert(arr != null);
+  var v = arr[0];
+  assert(v != null);
+  // assert(v == obj); // TODO: check if same Eo object pointer?
+  var expectedValue = 1234;
+  v.methodIntegralInA(expectedValue);
+  var actualValue = v.methodIntegralOutA();
+  assert(actualValue == expectedValue, actualValue + " == " + expectedValue);
+});
+
+// FIXME
+// startTest("method_array_of_strings", function() {
+//   var obj = new TestObject(null);
+//   var arr = obj.methodArrayOfStrings(null);
+//   assert(arr != null);
+//   assert(arr[0] === "foo");
+//   arr = obj.methodArrayOfStrings(arr);
+//   assert(arr != null);
+//   assert(arr[0] === "foo");
+// });
+
+startTest("method_array_of_ints", function() {
+  var obj = new TestObject(null);
+  var arr = obj.methodArrayOfInts(null);
+  assert(arr != null);
+  assert(arr[0] === 42);
+  arr = obj.methodArrayOfInts(arr);
+  assert(arr != null);
+  assert(arr[0] === 42);
+});
+
+startTest("method_array_of_bools", function() {
+  var obj = new TestObject(null);
+  var arr = obj.methodArrayOfBools(null);
+  assert(arr != null);
+  assert(arr[0] === true);
+  arr = obj.methodArrayOfBools(arr);
+  assert(arr != null);
+  assert(arr[0] === true);
+});
+
+startTest("method_array_of_doubles", function() {
+  var obj = new TestObject(null);
+  var arr = obj.methodArrayOfDoubles(null);
+  assert(arr != null);
+  assert(arr[0] === 42.0);
+  arr = obj.methodArrayOfDoubles(arr);
+  assert(arr != null);
+  assert(arr[0] === 42.0);
+});
+
+startTest("method_array_of_enums", function() {
+  var obj = new TestObject(null);
+  var arr = obj.methodArrayOfEnums(null);
+  assert(arr != null);
+  assert(arr[0] === suite.Test.EnumEx.THIRD);
+  arr = obj.methodArrayOfEnums(arr);
+  assert(arr != null);
+  assert(arr[0] === suite.Test.EnumEx.THIRD);
+});
+
+startTest("method_array_of_structs", function() {
+  var obj = new TestObject(null);
+  var arr = obj.methodArrayOfStructs(null);
+  assert(arr != null);
+  var s = arr[0];
+  assert(s != null);
+  assert(s.valueInt === 42);
+  assert(s.valueEnum === suite.Test.EnumEx.THIRD);
+  arr = obj.methodArrayOfStructs(arr);
+  s = arr[0];
+  assert(s != null);
+  assert(s.valueInt === 42);
+  assert(s.valueEnum === suite.Test.EnumEx.THIRD);
+});
+
+startTest("list_in_list_out", function() {
+  var obj = new TestObject(null);
+  var newList = obj.methodListWith42();
+  assert(newList != null);
+  var lis = obj.methodListInListOut(newList);
+  assert(lis != null);
+  // assert(lis == newList); // TODO: check same list pointer?
+  assert(lis[0] === 42);
+  assert(newList[0] === lis[0]);
+});
+
+startTest("method_list_of_objects", function() {
+  var obj = new TestObject(null);
+  var lis = obj.methodListOfObjects(null);
+  assert(lis != null);
+  assert(lis[0] != null);
+  lis = obj.methodListOfObjects(lis);
+  assert(lis != null);
+  var v = lis[0];
+  assert(v != null);
+  // assert(v == obj); // TODO: check if same Eo object pointer?
+  var expectedValue = 1234;
+  v.methodIntegralInA(expectedValue);
+  var actualValue = v.methodIntegralOutA();
+  assert(actualValue == expectedValue, actualValue + " == " + expectedValue);
+});
+
+// FIXME
+// startTest("method_list_of_strings", function() {
+//   var obj = new TestObject(null);
+//   var lis = obj.methodListOfStrings(null);
+//   assert(lis != null);
+//   assert(lis[0] === "foo");
+//   lis = obj.methodListOfStrings(lis);
+//   assert(lis != null);
+//   assert(lis[0] === "foo");
+// });
+
+startTest("method_list_of_ints", function() {
+  var obj = new TestObject(null);
+  var lis = obj.methodListOfInts(null);
+  assert(lis != null);
+  assert(lis[0] === 42);
+  lis = obj.methodListOfInts(lis);
+  assert(lis != null);
+  assert(lis[0] === 42);
+});
+
+startTest("method_list_of_bools", function() {
+  var obj = new TestObject(null);
+  var lis = obj.methodListOfBools(null);
+  assert(lis != null);
+  assert(lis[0] === true);
+  lis = obj.methodListOfBools(lis);
+  assert(lis != null);
+  assert(lis[0] === true);
+});
+
+startTest("method_list_of_doubles", function() {
+  var obj = new TestObject(null);
+  var lis = obj.methodListOfDoubles(null);
+  assert(lis != null);
+  assert(lis[0] === 42.0);
+  lis = obj.methodListOfDoubles(lis);
+  assert(lis != null);
+  assert(lis[0] === 42.0);
+});
+
+startTest("method_list_of_enums", function() {
+  var obj = new TestObject(null);
+  var lis = obj.methodListOfEnums(null);
+  assert(lis != null);
+  assert(lis[0] === suite.Test.EnumEx.THIRD);
+  lis = obj.methodListOfEnums(lis);
+  assert(lis != null);
+  assert(lis[0] === suite.Test.EnumEx.THIRD);
+});
+
+startTest("method_list_of_structs", function() {
+  var obj = new TestObject(null);
+  var lis = obj.methodListOfStructs(null);
+  assert(lis != null);
+  var s = lis[0];
+  assert(s != null);
+  assert(s.valueInt === 42);
+  assert(s.valueEnum === suite.Test.EnumEx.THIRD);
+  lis = obj.methodListOfStructs(lis);
+  s = lis[0];
+  assert(s != null);
+  assert(s.valueInt === 42);
+  assert(s.valueEnum === suite.Test.EnumEx.THIRD);
+});
+
+startTest("method_accessor_of_objects", function() {
+  var obj = new TestObject(null);
+  var acc = obj.methodAccessorOfObjects(null);
+  assert(acc != null);
+  assert(acc.get(0) != null);
+  acc = obj.methodAccessorOfObjects(acc);
+  assert(acc != null);
+  var v = acc.get(0);
+  assert(v != null);
+  var expectedValue = 1234;
+  v.methodIntegralInA(expectedValue);
+  var actualValue = v.methodIntegralOutA();
+  assert(actualValue == expectedValue, actualValue + " == " + expectedValue);
+});
+
+// FIXME
+// startTest("method_accessor_of_strings", function() {
+//   var obj = new TestObject(null);
+//   var acc = obj.methodAccessorOfStrings(null);
+//   assert(acc != null);
+//   assert(acc.get(0) === "foo");
+//   acc = obj.methodAccessorOfStrings(acc);
+//   assert(acc != null);
+//   assert(acc.get(0) === "foo");
+// });
+
+startTest("method_accessor_of_ints", function() {
+  var obj = new TestObject(null);
+  var acc = obj.methodAccessorOfInts(null);
+  assert(acc != null);
+  assert(acc.get(0) === 42);
+  acc = obj.methodAccessorOfInts(acc);
+  assert(acc != null);
+  assert(acc.get(0) === 42);
+});
+
+startTest("method_accessor_of_bools", function() {
+  var obj = new TestObject(null);
+  var acc = obj.methodAccessorOfBools(null);
+  assert(acc != null);
+  assert(acc.get(0) === true);
+  acc = obj.methodAccessorOfBools(acc);
+  assert(acc != null);
+  assert(acc.get(0) === true);
+});
+
+startTest("method_accessor_of_doubles", function() {
+  var obj = new TestObject(null);
+  var acc = obj.methodAccessorOfDoubles(null);
+  assert(acc != null);
+  assert(acc.get(0) === 42.0);
+  acc = obj.methodAccessorOfDoubles(acc);
+  assert(acc != null);
+  assert(acc.get(0) === 42.0);
+});
+
+startTest("method_accessor_of_enums", function() {
+  var obj = new TestObject(null);
+  var acc = obj.methodAccessorOfEnums(null);
+  assert(acc != null);
+  assert(acc.get(0) === suite.Test.EnumEx.THIRD);
+  acc = obj.methodAccessorOfEnums(acc);
+  assert(acc != null);
+  assert(acc.get(0) === suite.Test.EnumEx.THIRD);
+});
+
+startTest("method_accessor_of_structs", function() {
+  var obj = new TestObject(null);
+  var acc = obj.methodAccessorOfStructs(null);
+  assert(acc != null);
+  var s = acc.get(0);
+  assert(s != null);
+  assert(s.valueInt === 42);
+  assert(s.valueEnum === suite.Test.EnumEx.THIRD);
+  acc = obj.methodAccessorOfStructs(acc);
+  assert(acc != null);
+  s = acc.get(0);
+  assert(s != null);
+  assert(s.valueInt === 42);
+  assert(s.valueEnum === suite.Test.EnumEx.THIRD);
+});
+
+// Combinations of complex types //
+
+// FIXME
+// startTest("method_array_of_arrays_of_ints", function() {
+//   var obj = new TestObject(null);
+//   var arr = obj.methodArrayOfArraysOfInts(null);
+//   assert(arr != null);
+//   var a = arr[0];
+//   assert(a != null);
+//   assert(a[0] === 42);
+//   arr = obj.methodArrayOfArraysOfInts(arr);
+//   assert(arr != null);
+//   a = arr[0];
+//   assert(a != null);
+//   assert(a[0] === 42);
+// });
+
+// FIXME
+// startTest("method_list_of_lists_of_ints", function() {
+//   var obj = new TestObject(null);
+//   var lis = obj.methodListOfListsOfInts(null);
+//   assert(lis != null);
+//   var l = lis[0];
+//   assert(l != null);
+//   assert(l[0] === 42);
+//   lis = obj.methodListOfListsOfInts(lis);
+//   assert(lis != null);
+//   l = lis[0];
+//   assert(l != null);
+//   assert(l[0] === 42);
+// });
+
+// FIXME
+// startTest("method_array_of_lists_of_ints", function() {
+//   var obj = new TestObject(null);
+//   var arr = obj.methodArrayOfListsOfInts(null);
+//   assert(arr != null);
+//   var l = arr[0];
+//   assert(l != null);
+//   assert(l[0] === 42);
+//   arr = obj.methodArrayOfListsOfInts(arr);
+//   assert(arr != null);
+//   l = arr[0];
+//   assert(l != null);
+//   assert(l[0] === 42);
+// });
+
+// FIXME
+// startTest("method_list_of_arrays_of_ints", function() {
+//   var obj = new TestObject(null);
+//   var lis = obj.methodListOfArraysOfInts(null);
+//   assert(lis != null);
+//   var a = lis[0];
+//   assert(a != null);
+//   assert(a[0] === 42);
+//   lis = obj.methodListOfArraysOfInts(lis);
+//   assert(lis != null);
+//   a = lis[0];
+//   assert(a != null);
+//   assert(a[0] === 42);
+// });
+
+startTest("new Constructor_Method_Class", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  assert(obj);
+  assert(obj.getFail() == false, "object fail flag set");
+});
+
+startTest("Constructor_Method_Class method1", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  obj.method1(2);
+  assert(obj.getFail() == false, "object fail flag set");
+});
+
+startTest("Constructor_Method_Class method2", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  var r = obj.method2(3);
+  assert(r === 5);
+  assert(obj.getFail() == false, "object fail flag set");
+});
+
+startTest("Constructor_Method_Class method3", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  obj.method3(3, 11.1);
+  assert(obj.getFail() == false, "object fail flag set");
+});
+
+startTest("Constructor_Method_Class method4", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  var r = obj.method4(3, 11.1);
+  assert(r == 5);
+  assert(obj.getFail() == false, "object fail flag set");
+});
+
+startTest("Constructor_Method_Class method3 less parameters than expected", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  expectException(function() {
+    obj.method3(3);
+  });
+});
+
+startTest("Constructor_Method_Class constructor less parameters than expected", function() {
+  expectException(function() {
+    var obj = new ConstructorMethodClass(null, 5);
+  });
+});
+
+startTest("Constructor_Method_Class constructor wrong parameter types", function() {
+  expectException(function() {
+    var obj = new ConstructorMethodClass(null, 5.1, 10);
+  });
+});
+
+// Out parameters //
+
+startTest("Constructor_Method_Class outmethod1", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  var r = obj.outmethod1();
+  assert(r == 5);
+  assert(obj.getFail() == false, "object fail flag set");
+});
+
+startTest("Constructor_Method_Class outmethod2", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  var r = obj.outmethod2();
+  assert(Array.isArray(r));
+  printInfo("Return is array from outmethod2");
+  assert(r[0] == 11);
+  assert(r[1] == 10);
+  assert(obj.getFail() == false, "object fail flag set");
+});
+
+startTest("Constructor_Method_Class outmethod3", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  var r = obj.outmethod3();
+  assert(Array.isArray(r));
+  printInfo("Return is array from outmethod3");
+  assert(r[0] == 11);
+  assert(r[1] == 5.1);
+  assert(obj.getFail() == false, "object fail flag set");
+});
+
+startTest("Constructor_Method_Class classoutmethod1", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  var c = obj.classoutmethod1(5, 10.0);
+  assert(c);
+  var r = c.method4(3, 11.1);
+  assert(r == 5);
+  assert(c.getFail() == false, "object fail flag set");
+  assert(obj.getFail() == false, "object fail flag set");
+});
+
+startTest("Constructor_Method_Class classoutmethod2", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  printInfo('1');
+  var c = obj.classoutmethod2(5, 10.0);
+  assert(c);
+  var r = c.method4(3, 11.1);
+  assert(r);
+  assert(r == 5);
+  assert(c.getFail() == false, "object fail flag set");
+  assert(obj.getFail() == false, "object fail flag set");
+});
+
+startTest("cast", function() {
+  var obj = new ConstructorMethodClass(null, 5, 10.0);
+  var c = obj.classoutmethod1(5, 10.0);
+  print('classoutmethod1');
+  assert(c);
+  var d = c.cast('Constructor_Method_Class');
+  assert(d);
+});
+
+if (!suiteSuccess) {
+  print ("[ Total tests run: %s ]", suiteOk + suiteFail.length);
+  print ("[ Total successful: %s ]", suiteOk);
+  print ("[ Total failures: %s ]", suiteFail.length);
+  print ("[ Tests failed: ]");
+  for (var i = 0; i < suiteFail.length; i++) {
+    print ("[    %s]", suiteFail[i]);
+  };
+  assert(false, "[ Test suite fail ]");
+} else {
+  print ("[ Test execution with success ]");
+  print ("[ Total tests run: %s ]", suiteOk);
+}
+
+exit();
diff --git a/src/tests/eolian_js/eolian_js_test_constructor_method_impl.c b/src/tests/eolian_js/eolian_js_test_constructor_method_impl.c
new file mode 100644 (file)
index 0000000..1f454eb
--- /dev/null
@@ -0,0 +1,147 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eo.h>
+#include <Ecore.h>
+
+#include <stdlib.h>
+
+#include "constructor_method_class.eo.h"
+
+#include <check.h>
+
+struct _Constructor_Method_Class_Data
+{
+  Eina_Bool fail;
+};
+typedef struct _Constructor_Method_Class_Data Constructor_Method_Class_Data;
+
+#define MY_CLASS CONSTRUCTOR_METHOD_CLASS_CLASS
+
+EOLIAN static Eo_Base *
+_constructor_method_class_eo_base_constructor(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd)
+{
+  pd->fail = EINA_FALSE;
+  return eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+}
+
+EOLIAN static void
+_constructor_method_class_constructor1(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd, int one)
+{
+  fprintf(stderr, "one == %d\n", one);
+  fflush(stderr);
+  if (one != 5)
+    pd->fail = EINA_TRUE;
+}
+
+EOLIAN static void
+_constructor_method_class_constructor2(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd, double two)
+{
+  fprintf(stderr, "two == %f\n", two);
+  fflush(stderr);
+  if (two != 10.0)
+    pd->fail = EINA_TRUE;
+}
+
+EOLIAN static Eo *
+_constructor_method_class_eo_base_finalize(Eo *obj, Constructor_Method_Class_Data *pd)
+{
+  if (pd->fail)
+    return NULL;
+
+  return eo_do_super_ret(obj, MY_CLASS, obj, eo_finalize());
+}
+
+EOLIAN static Eina_Bool
+_constructor_method_class_fail_get(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd)
+{
+  return pd->fail;
+}
+
+EOLIAN static void
+_constructor_method_class_method1(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd, int one)
+{
+  fprintf(stderr, "method1 one == %d\n", one);
+  fflush(stderr);
+  if (one != 2)
+    pd->fail = EINA_TRUE;
+}
+
+EOLIAN static int
+_constructor_method_class_method2(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd, int one)
+{
+  fprintf(stderr, "method2 one == %d\n", one);
+  fflush(stderr);
+  if (one != 3)
+    pd->fail = EINA_TRUE;
+  return 5;
+}
+
+EOLIAN static void
+_constructor_method_class_method3(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd, int one, double two)
+{
+  fprintf(stderr, "method3 one == %d two == %f\n", one, two);
+  fflush(stderr);
+  if (one != 3)
+    pd->fail = EINA_TRUE;
+  if (two != 11.1)
+    pd->fail = EINA_TRUE;
+}
+
+EOLIAN static int
+_constructor_method_class_method4(Eo * obj EINA_UNUSED, Constructor_Method_Class_Data *pd, int one, double two)
+{
+  fprintf(stderr, "method4 one == %d two == %f\n", one, two);
+  fflush(stderr);
+  if (one != 3)
+    pd->fail = EINA_TRUE;
+  if (two != 11.1)
+    pd->fail = EINA_TRUE;
+  return 5;
+}
+
+EOLIAN static void
+_constructor_method_class_outmethod1(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd EINA_UNUSED, int *one)
+{
+  fprintf(stderr, "outmethod1\n");
+  fflush(stderr);
+  *one = 5;
+}
+
+EOLIAN static int
+_constructor_method_class_outmethod2(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd EINA_UNUSED, int *one)
+{
+  fprintf(stderr, "outmethod2\n");
+  fflush(stderr);
+  *one = 10;
+  return 11;
+}
+
+EOLIAN static void
+_constructor_method_class_outmethod3(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd EINA_UNUSED, int *one, double *two)
+{
+  fprintf(stderr, "outmethod3\n");
+  fflush(stderr);
+  *one = 11;
+  *two = 5.1;
+}
+
+EOLIAN static Constructor_Method_Class *
+_constructor_method_class_classoutmethod1(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd EINA_UNUSED, int one, double two)
+{
+  fprintf(stderr, "classoutmethod1\n");
+  fflush(stderr);
+  return eo_add(MY_CLASS, NULL, constructor_method_class_constructor1(one), constructor_method_class_constructor2(two));
+}
+
+EOLIAN static void
+_constructor_method_class_classoutmethod2(Eo* obj EINA_UNUSED, Constructor_Method_Class_Data *pd EINA_UNUSED, int one, double two, Constructor_Method_Class **out_class)
+{
+  fprintf(stderr, "classoutmethod2\n");
+  fflush(stderr);
+  *out_class = eo_add(MY_CLASS, NULL, constructor_method_class_constructor1(one), constructor_method_class_constructor2(two));
+}
+
+
+#include <constructor_method_class.eo.c>
diff --git a/src/tests/eolian_js/eolian_js_test_eolian_js_binding.cc b/src/tests/eolian_js/eolian_js_test_eolian_js_binding.cc
new file mode 100644 (file)
index 0000000..dbdd016
--- /dev/null
@@ -0,0 +1,44 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eo_Js.hh>
+#include <Eina.hh>
+#include <Eo.hh>
+
+#include <check.h>
+
+
+#include <iostream>
+#include <cassert>
+#include <fstream>
+
+typedef struct _Elm_Calendar_Mark Elm_Calendar_Mark;
+
+#include "constructor_method_class.eo.js.cc"
+#include "test_object.eo.js.cc"
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+#  define EAPI __declspec(dllimport)
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+void eolian_js_test_register_eolian_js_binding(v8::Handle<v8::Object> exports)
+{
+  v8::Isolate* isolate = v8::Isolate::GetCurrent();
+  test::register_object(exports, isolate);
+  register_constructor_method_class(exports, isolate);
+}
diff --git a/src/tests/eolian_js/eolian_js_test_evas_box.cc b/src/tests/eolian_js/eolian_js_test_evas_box.cc
new file mode 100644 (file)
index 0000000..e859f2a
--- /dev/null
@@ -0,0 +1,151 @@
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eo_Js.hh>
+#include <Eina.hh>
+#include <Eo.hh>
+
+#include <check.h>
+
+#include <iostream>
+
+#include <cassert>
+#include <tuple>
+
+namespace evas {
+EAPI void register_box(v8::Handle<v8::Object> global, v8::Isolate* isolate);
+}
+
+namespace {
+
+static const char script[] =
+  "function assert(condition, message) {\n"
+  "  if (!condition) {\n"
+  "      print(\"Assertion failed \", message);\n"
+  "      throw message || \"Assertion failed\";\n"
+  "  }\n"
+  "}\n"
+  "print(\"teste\");\n"
+  "x = new Box();\n"
+  ;
+
+const char* ToCString(const v8::String::Utf8Value& value) {
+  return *value ? *value : "<string conversion failed>";
+}
+
+// Executes a string within the current v8 context.
+bool ExecuteString(v8::Isolate* isolate,
+                   v8::Handle<v8::String> source,
+                   v8::Handle<v8::Value> name)
+{
+  efl::eina::js::compatibility_handle_scope handle_scope(isolate);
+  v8::TryCatch try_catch;
+  v8::ScriptOrigin origin(name);
+  v8::Handle<v8::Script> script = v8::Script::Compile(source, &origin);
+  if (script.IsEmpty()) {
+    std::abort();
+    // Print errors that happened during compilation.
+    // if (report_exceptions)
+    //   ReportException(isolate, &try_catch);
+    return false;
+  }
+  else
+  {
+    v8::Handle<v8::Value> result = script->Run();
+    if (result.IsEmpty()) {
+      std::cout << "Failed with exception thrown" << std::endl;
+      assert(try_catch.HasCaught());
+      std::abort();
+      // Print errors that happened during execution.
+      // if (report_exceptions)
+      //   ReportException(isolate, &try_catch);
+      return false;
+    } else {
+      assert(!try_catch.HasCaught());
+      // if (print_result && !result->IsUndefined()) {
+      //   // If all went well and the result wasn't undefined then print
+      //   // the returned value.
+      //   v8::String::Utf8Value str(result);
+      //   const char* cstr = ToCString(str);
+      //   printf("%s\n", cstr);
+      // }
+      return true;
+    }
+  }
+}
+
+efl::eina::js::compatibility_return_type Print(efl::eina::js::compatibility_callback_info_type args) {
+  bool first = true;
+  for (int i = 0; i < args.Length(); i++) {
+    efl::eina::js::compatibility_handle_scope handle_scope(args.GetIsolate());
+    if (first) {
+      first = false;
+    } else {
+      printf(" ");
+    }
+    v8::String::Utf8Value str(args[i]);
+    const char* cstr = ToCString(str);
+    printf("%s", cstr);
+  }
+  printf("\n");
+  fflush(stdout);
+}
+
+START_TEST(eolian_js_test_evas_box)
+{
+  int argc = 1;
+  const char* argv[] = {"test"};
+  efl::eina::eina_init eina_init;
+  efl::eo::eo_init eo_init;
+  
+  //v8::V8::InitializeICU();
+  v8::V8::Initialize();
+  v8::V8::SetFlagsFromCommandLine(&argc, const_cast<char**>(argv), true);
+
+  v8::Isolate* isolate = efl::eina::js::compatibility_isolate_new();
+
+  v8::Isolate::Scope isolate_scope(isolate);
+  
+  assert(isolate != 0);
+
+  v8::Handle<v8::Context> context;
+  efl::eina::js::compatibility_handle_scope handle_scope(isolate);
+
+  {
+    // Create a template for the global object.
+    v8::Handle<v8::ObjectTemplate> global = efl::eina::js::compatibility_new<v8::ObjectTemplate>(isolate);
+    // Bind the global 'print' function to the C++ Print callback.
+    global->Set(efl::eina::js::compatibility_new<v8::String>(isolate, "print"),
+                efl::eina::js::compatibility_new<v8::FunctionTemplate>(isolate, Print));
+
+    context = efl::eina::js::compatibility_new<v8::Context>(isolate, nullptr, global);
+
+  }
+  if (context.IsEmpty()) {
+    fprintf(stderr, "Error creating context\n");
+  }
+  context->Enter();
+  {
+    // Enter the execution environment before evaluating any code.
+    v8::Context::Scope context_scope(context);
+    v8::Local<v8::String> name(efl::eina::js::compatibility_new<v8::String>(/*context->GetIsolate()*/nullptr, "(shell)"));
+
+    evas::register_box(context->Global(), isolate);
+
+    efl::eina::js::compatibility_handle_scope handle_scope(/*context->GetIsolate()*/nullptr);
+    ExecuteString(/*context->GetIsolate()*/isolate,
+                  efl::eina::js::compatibility_new<v8::String>/*FromUtf8*/(/*context->GetIsolate()*/nullptr, script),
+                  name);
+  }
+  context->Exit();
+}
+END_TEST
+
+}
+
+void eolian_js_test_evas_box(TCase* tc)
+{
+   tcase_add_test(tc, eolian_js_test_evas_box);
+}
diff --git a/src/tests/eolian_js/eolian_js_test_test_object_impl.c b/src/tests/eolian_js/eolian_js_test_test_object_impl.c
new file mode 100644 (file)
index 0000000..6f35b7e
--- /dev/null
@@ -0,0 +1,620 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Eo.h>
+#include <Ecore.h>
+
+#include "test_object.eo.h"
+
+#include <check.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <math.h>
+#include <stdlib.h>
+
+struct _Test_Object_Data
+{
+   int a;
+};
+
+typedef struct _Test_Object_Data Test_Object_Data;
+
+#define MY_CLASS TEST_OBJECT_CLASS
+
+EOLIAN static Eo_Base *
+_test_object_eo_base_constructor(Eo* obj, Test_Object_Data *pd)
+{
+  fprintf(stdout, "_test_object_eo_base_constructor\n");
+
+  pd->a = 0;
+  return eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+}
+
+EOLIAN static Eo *
+_test_object_eo_base_finalize(Eo *obj, Test_Object_Data *pd EINA_UNUSED)
+{
+  fprintf(stdout, "_test_object_eo_base_finalize\n");
+
+  return eo_do_super_ret(obj, MY_CLASS, obj, eo_finalize());
+}
+
+EOLIAN static void
+_test_object_eo_base_destructor(Eo* obj, Test_Object_Data *pd EINA_UNUSED)
+{
+  fprintf(stdout, "_test_object_eo_base_destructor\n");
+  eo_do_super(obj, MY_CLASS, eo_destructor());
+}
+
+
+EOLIAN static void
+_test_object_method_integral_in_a(Eo* obj EINA_UNUSED,
+                                    Test_Object_Data *pd,
+                                    int a)
+{
+  fprintf(stdout, "_test_object_method_integral_in_a(%d)\n", a);
+  pd->a = a;
+}
+
+EOLIAN static void
+_test_object_method_integral_out_a(Eo* obj EINA_UNUSED,
+                                     Test_Object_Data *pd,
+                                     int *a)
+{
+  fprintf(stdout, "_test_object_method_integral_out_a(%p)\n", a);
+  *a = pd->a;
+}
+
+EOLIAN static void
+_test_object_method_integral_inout(Eo* obj EINA_UNUSED,
+                                     Test_Object_Data *pd EINA_UNUSED,
+                                     int *a)
+{
+  fprintf(stdout, "_test_object_method_integral_inout(%d [%p])\n", *a, a);
+  *a = -(*a);
+}
+
+EOLIAN static int
+_test_object_method_integral_return_a(Eo* obj EINA_UNUSED,
+                                        Test_Object_Data *pd)
+{
+  fprintf(stdout, "_test_object_method_integral_return_a()\n");
+  return pd->a;
+}
+
+EOLIAN static Eina_Bool
+_test_object_method_div_mod(Eo* obj EINA_UNUSED,
+                              Test_Object_Data *pd EINA_UNUSED,
+                              int a,
+                              int b,
+                              int *quotient,
+                              int *remainder)
+{
+  fprintf(stdout, "_test_object_method_div_mod(%d, %d, %p, %p)\n", a, b, quotient, remainder);
+  if (0 == b) return EINA_FALSE;
+  *quotient = a / b;
+  *remainder = a % b;
+  return EINA_TRUE;
+}
+
+EOLIAN static Eina_Bool
+_test_object_method_and(Eo* obj EINA_UNUSED,
+                          Test_Object_Data *pd EINA_UNUSED,
+                          Eina_Bool a,
+                          Eina_Bool b)
+{
+  fprintf(stdout, "_test_object_method_and(%d, %d)\n", a, b);
+  return a && b;
+}
+
+EOLIAN static double
+_test_object_method_modf(Eo* obj EINA_UNUSED,
+                           Test_Object_Data *pd EINA_UNUSED,
+                           double x,
+                           double *int_part)
+{
+  fprintf(stdout, "_test_object_method_modf(%f, %p)\n", x, int_part);
+  return modf(x, int_part);
+}
+
+EOLIAN static void
+_test_object_method_uppercase(Eo* obj EINA_UNUSED,
+                                Test_Object_Data *pd EINA_UNUSED,
+                                char **str)
+{
+  fprintf(stdout, "_test_object_method_uppercase('%s')\n", *str);
+  if (!*str) return;
+
+  char *p = *str;
+  while ('\0' != *p)
+    {
+       *p = toupper(*p);
+       p++;
+    }
+}
+
+EOLIAN static Eina_Bool
+_test_object_method_in_null(Eo* obj EINA_UNUSED,
+                              Test_Object_Data *pd EINA_UNUSED,
+                              char *a)
+{
+  fprintf(stdout, "_test_object_method_in_null(%p)\n", a);
+  return NULL == a;
+}
+
+EOLIAN static Eina_Bool
+_test_object_method_out_null(Eo* obj EINA_UNUSED,
+                               Test_Object_Data *pd EINA_UNUSED,
+                               char **a)
+{
+  fprintf(stdout, "_test_object_method_out_null(%p)\n", a);
+  *a = NULL;
+  return EINA_TRUE;
+}
+
+EOLIAN static Eina_Bool
+_test_object_method_inout_null(Eo* obj EINA_UNUSED,
+                                 Test_Object_Data *pd EINA_UNUSED,
+                                 char **a)
+{
+  fprintf(stdout, "_test_object_method_inout_null(%p)\n", a);
+  return NULL == *a;
+}
+
+EOLIAN static char *
+_test_object_method_return_null(Eo* obj EINA_UNUSED,
+                                  Test_Object_Data *pd EINA_UNUSED)
+{
+  fprintf(stdout, "_test_object_method_return_null()\n");
+  return NULL;
+}
+
+EOLIAN static void
+_test_object_call_event(Eo* obj, Test_Object_Data *pd EINA_UNUSED)
+{
+   fprintf(stderr, "_test_object_event_call()\n"); fflush(stderr);
+   static Test_Struct_Ex s = {42, TEST_ENUM_EX_THIRD};
+   eo_do(obj, eo_event_callback_call(TEST_OBJECT_EVENT_TEST, NULL));
+   eo_do(obj, eo_event_callback_call(TEST_OBJECT_EVENT_TEST_STRUCTARG, &s));
+   eo_do(obj, eo_event_callback_call(TEST_OBJECT_EVENT_TEST_STRINGARG, "foo"));
+}
+
+EOLIAN static char *
+_test_object_method_null(Eo* obj EINA_UNUSED,
+                           Test_Object_Data *pd EINA_UNUSED,
+                           char *in,
+                           char **out,
+                           char **inout)
+{
+  fprintf(stdout, "_test_object_method_null(%p, %p, %p)\n", in, out, inout);
+  assert(!in);
+  *out = NULL;
+  *inout = NULL;
+  return NULL;
+}
+
+// Arrays //
+
+EOLIAN static int
+_test_object_method_array_at(Eo* obj EINA_UNUSED,
+                               Test_Object_Data *pd EINA_UNUSED,
+                               Eina_Array *array,
+                               int index)
+{
+  fprintf(stdout, "_test_object_method_array_at(%p, %d)\n", array, index);
+  return *((int*)eina_array_data_get(array, index));
+}
+
+EOLIAN static Eina_Array *
+_test_object_method_array_with_42(Eo* obj EINA_UNUSED,
+                                    Test_Object_Data *pd EINA_UNUSED)
+{
+  fprintf(stdout, "_test_object_method_array_with_42()\n");
+  Eina_Array *arr = eina_array_new(2);
+  int* n = malloc(sizeof(int));
+  *n = 42;
+  eina_array_push(arr, n);
+  return arr;
+}
+
+EOLIAN static void
+_test_object_method_array_in_array_out(Eo* obj EINA_UNUSED,
+                                         Test_Object_Data *pd EINA_UNUSED,
+                                         Eina_Array *a_in,
+                                         Eina_Array **a_out)
+{
+  fprintf(stdout, "_test_object_method_array_in_array_out(%p, %p)\n", a_in, a_out);
+  *a_out = a_in;
+}
+
+EOLIAN static Eina_Array *
+_test_object_method_array_of_objects(Eo* obj,
+                                       Test_Object_Data *pd EINA_UNUSED,
+                                       Eina_Array *a_in)
+{
+  fprintf(stdout, "_test_object_method_array_of_objects(%p)\n", a_in);
+  if (a_in) return a_in;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, obj);
+  return arr;
+}
+
+
+EOLIAN static Eina_Array *
+_test_object_method_array_of_strings(Eo* obj EINA_UNUSED,
+                                       Test_Object_Data *pd EINA_UNUSED,
+                                       Eina_Array *a_in)
+{
+  fprintf(stdout, "_test_object_method_array_of_strings(%p)\n", a_in);
+  if (a_in) return a_in;
+  Eina_Array *arr = eina_array_new(2);
+  const char* v = "foo";
+  fprintf(stdout, "v = %p\n", v);
+  eina_array_push(arr, v);
+  return arr;
+}
+
+EOLIAN static Eina_Array *
+_test_object_method_array_of_ints(Eo* obj EINA_UNUSED,
+                                    Test_Object_Data *pd EINA_UNUSED,
+                                    Eina_Array *a_in)
+{
+  fprintf(stdout, "_test_object_method_array_of_ints(%p)\n", a_in);
+  if (a_in) return a_in;
+  int *v = malloc(sizeof(int));
+  *v = 42;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return arr;
+}
+
+EOLIAN static Eina_Array *
+_test_object_method_array_of_bools(Eo* obj EINA_UNUSED,
+                                     Test_Object_Data *pd EINA_UNUSED,
+                                     Eina_Array *a_in)
+{
+  fprintf(stdout, "_test_object_method_array_of_bools(%p)\n", a_in);
+  if (a_in) return a_in;
+  Eina_Bool *v = malloc(sizeof(Eina_Bool));
+  *v = EINA_TRUE;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return arr;
+}
+
+EOLIAN static Eina_Array *
+_test_object_method_array_of_doubles(Eo* obj EINA_UNUSED,
+                                       Test_Object_Data *pd EINA_UNUSED,
+                                       Eina_Array *a_in)
+{
+  fprintf(stdout, "_test_object_method_array_of_doubles(%p)\n", a_in);
+  if (a_in) return a_in;
+  double *v = malloc(sizeof(double));
+  *v = 42;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return arr;
+}
+
+EOLIAN static Eina_Array *
+_test_object_method_array_of_enums(Eo* obj EINA_UNUSED,
+                                     Test_Object_Data *pd EINA_UNUSED,
+                                     Eina_Array *a_in)
+{
+  fprintf(stdout, "_test_object_method_array_of_enums(%p)\n", a_in);
+  if (a_in) return a_in;
+  Test_Enum_Ex *v = malloc(sizeof(Test_Enum_Ex));
+  *v = TEST_ENUM_EX_THIRD;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return arr;
+}
+
+EOLIAN static Eina_Array *
+_test_object_method_array_of_structs(Eo* obj EINA_UNUSED,
+                                       Test_Object_Data *pd EINA_UNUSED,
+                                       Eina_Array *a_in)
+{
+  fprintf(stdout, "_test_object_method_array_of_structs(%p)\n", a_in);
+  if (a_in) return a_in;
+  Test_Struct_Ex *v = malloc(sizeof(Test_Struct_Ex));
+  v->value_int = 42;
+  v->value_enum = TEST_ENUM_EX_THIRD;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return arr;
+}
+
+EOLIAN static Eina_Array *
+_test_object_method_array_of_arrays_of_ints(Eo* obj EINA_UNUSED,
+                                              Test_Object_Data *pd EINA_UNUSED,
+                                              Eina_Array *a_in)
+{
+  fprintf(stdout, "_test_object_method_array_of_arrays_of_ints(%p)\n", a_in);
+  if (a_in) return a_in;
+  int *v = malloc(sizeof(int));
+  *v = 42;
+  Eina_Array *a1 = eina_array_new(2);
+  eina_array_push(a1, v);
+  Eina_Array *a2 = eina_array_new(2);
+  eina_array_push(a2, a1);
+  return a2;
+}
+
+// Lists //
+
+EOLIAN static Eina_List *
+_test_object_method_list_with_42(Eo* obj EINA_UNUSED,
+                                   Test_Object_Data *pd EINA_UNUSED)
+{
+  fprintf(stdout, "_test_object_method_list_with_42()\n");
+  int* n = malloc(sizeof(int));
+  *n = 42;
+  return eina_list_append(NULL, n);
+}
+
+EOLIAN static void
+_test_object_method_list_in_list_out(Eo* obj EINA_UNUSED,
+                                       Test_Object_Data *pd EINA_UNUSED,
+                                       Eina_List *l_in,
+                                       Eina_List **l_out)
+{
+  fprintf(stdout, "_test_object_method_list_in_list_out(%p , %p)\n", l_in, l_out);
+  *l_out = l_in;
+}
+
+EOLIAN static Eina_List *
+_test_object_method_list_of_objects(Eo* obj,
+                                      Test_Object_Data *pd EINA_UNUSED,
+                                      Eina_List *l_in)
+{
+  fprintf(stdout, "_test_object_method_list_of_objects(%p)\n", l_in);
+  if (l_in) return l_in;
+  return eina_list_append(NULL, obj);
+}
+
+
+EOLIAN static Eina_List *
+_test_object_method_list_of_strings(Eo* obj EINA_UNUSED,
+                                      Test_Object_Data *pd EINA_UNUSED,
+                                      Eina_List *l_in)
+{
+  fprintf(stdout, "_test_object_method_list_of_strings(%p)\n", l_in);
+  if (l_in) return l_in;
+  return eina_list_append(NULL, "foo");
+}
+
+EOLIAN static Eina_List *
+_test_object_method_list_of_ints(Eo* obj EINA_UNUSED,
+                                   Test_Object_Data *pd EINA_UNUSED,
+                                   Eina_List *l_in)
+{
+  fprintf(stdout, "_test_object_method_list_of_ints(%p)\n", l_in);
+  if (l_in) return l_in;
+  int *v = malloc(sizeof(int));
+  *v = 42;
+  return eina_list_append(NULL, v);
+}
+
+EOLIAN static Eina_List *
+_test_object_method_list_of_bools(Eo* obj EINA_UNUSED,
+                                    Test_Object_Data *pd EINA_UNUSED,
+                                    Eina_List *l_in)
+{
+  fprintf(stdout, "_test_object_method_list_of_bools(%p)\n", l_in);
+  if (l_in) return l_in;
+  Eina_Bool *v = malloc(sizeof(Eina_Bool));
+  *v = EINA_TRUE;
+  return eina_list_append(NULL, v);
+}
+
+EOLIAN static Eina_List *
+_test_object_method_list_of_doubles(Eo* obj EINA_UNUSED,
+                                      Test_Object_Data *pd EINA_UNUSED,
+                                      Eina_List *l_in)
+{
+  fprintf(stdout, "_test_object_method_list_of_doubles(%p)\n", l_in);
+  if (l_in) return l_in;
+  double *v = malloc(sizeof(double));
+  *v = 42;
+  return eina_list_append(NULL, v);
+}
+
+EOLIAN static Eina_List *
+_test_object_method_list_of_enums(Eo* obj EINA_UNUSED,
+                                    Test_Object_Data *pd EINA_UNUSED,
+                                    Eina_List *l_in)
+{
+  fprintf(stdout, "_test_object_method_list_of_enums(%p)\n", l_in);
+  if (l_in) return l_in;
+  Test_Enum_Ex *v = malloc(sizeof(Test_Enum_Ex));
+  *v = TEST_ENUM_EX_THIRD;
+  return eina_list_append(NULL, v);
+}
+
+EOLIAN static Eina_List *
+_test_object_method_list_of_structs(Eo* obj EINA_UNUSED,
+                                      Test_Object_Data *pd EINA_UNUSED,
+                                      Eina_List *l_in)
+{
+  fprintf(stdout, "_test_object_method_list_of_structs(%p)\n", l_in);
+  if (l_in) return l_in;
+  Test_Struct_Ex *v = malloc(sizeof(Test_Struct_Ex));
+  v->value_int = 42;
+  v->value_enum = TEST_ENUM_EX_THIRD;
+  return eina_list_append(NULL, v);
+}
+
+// Accessors //
+
+EOLIAN static Eina_Accessor *
+_test_object_method_accessor_of_objects(Eo* obj,
+                                          Test_Object_Data *pd EINA_UNUSED,
+                                          Eina_Accessor *a_in)
+{
+  fprintf(stdout, "_test_object_method_accessor_of_objects(%p)\n", a_in);
+  if (a_in) return a_in;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, obj);
+  return eina_array_accessor_new(arr);
+}
+
+EOLIAN static Eina_Accessor *
+_test_object_method_accessor_of_strings(Eo* obj EINA_UNUSED,
+                                          Test_Object_Data *pd EINA_UNUSED,
+                                          Eina_Accessor *a_in)
+{
+  fprintf(stdout, "_test_object_method_accessor_of_strings(%p)\n", a_in);
+  if (a_in) return a_in;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, "foo");
+  return eina_array_accessor_new(arr);
+}
+
+EOLIAN static Eina_Accessor *
+_test_object_method_accessor_of_ints(Eo* obj EINA_UNUSED,
+                                       Test_Object_Data *pd EINA_UNUSED,
+                                       Eina_Accessor *a_in)
+{
+  fprintf(stdout, "_test_object_method_accessor_of_ints(%p)\n", a_in);
+  if (a_in) return a_in;
+  int *v = malloc(sizeof(int));
+  *v = 42;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return eina_array_accessor_new(arr);
+}
+
+EOLIAN static Eina_Accessor *
+_test_object_method_accessor_of_bools(Eo* obj EINA_UNUSED,
+                                        Test_Object_Data *pd EINA_UNUSED,
+                                        Eina_Accessor *a_in)
+{
+  fprintf(stdout, "_test_object_method_accessor_of_bools(%p)\n", a_in);
+  if (a_in) return a_in;
+  Eina_Bool *v = malloc(sizeof(Eina_Bool));
+  *v = EINA_TRUE;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return eina_array_accessor_new(arr);
+}
+
+EOLIAN static Eina_Accessor *
+_test_object_method_accessor_of_doubles(Eo* obj EINA_UNUSED,
+                                          Test_Object_Data *pd EINA_UNUSED,
+                                          Eina_Accessor *a_in)
+{
+  fprintf(stdout, "_test_object_method_accessor_of_doubles(%p)\n", a_in);
+  if (a_in) return a_in;
+  double *v = malloc(sizeof(double));
+  *v = 42.0;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return eina_array_accessor_new(arr);
+}
+
+EOLIAN static Eina_Accessor *
+_test_object_method_accessor_of_enums(Eo* obj EINA_UNUSED,
+                                        Test_Object_Data *pd EINA_UNUSED,
+                                        Eina_Accessor *a_in)
+{
+  fprintf(stdout, "_test_object_method_accessor_of_enums(%p)\n", a_in);
+  if (a_in) return a_in;
+  Test_Enum_Ex *v = malloc(sizeof(Test_Enum_Ex));
+  *v = TEST_ENUM_EX_THIRD;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return eina_array_accessor_new(arr);
+}
+
+EOLIAN static Eina_Accessor *
+_test_object_method_accessor_of_structs(Eo* obj EINA_UNUSED,
+                                          Test_Object_Data *pd EINA_UNUSED,
+                                          Eina_Accessor *a_in)
+{
+  fprintf(stdout, "_test_object_method_accessor_of_structs(%p)\n", a_in);
+  if (a_in) return a_in;
+  Test_Struct_Ex *v = malloc(sizeof(Test_Struct_Ex));
+  v->value_int = 42;
+  v->value_enum = TEST_ENUM_EX_THIRD;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return eina_array_accessor_new(arr);
+}
+
+// Combinations of complex types
+
+EOLIAN static Eina_List *
+_test_object_method_list_of_lists_of_ints(Eo* obj EINA_UNUSED,
+                                            Test_Object_Data *pd EINA_UNUSED,
+                                            Eina_List *l_in)
+{
+  fprintf(stdout, "_test_object_method_list_of_lists_of_ints(%p)\n", l_in);
+  if (l_in) return l_in;
+  int *v = malloc(sizeof(int));
+  *v = 42;
+  return eina_list_append(NULL, eina_list_append(NULL, v));
+}
+
+EOLIAN static Eina_Array *
+_test_object_method_array_of_lists_of_ints(Eo* obj EINA_UNUSED,
+                                             Test_Object_Data *pd EINA_UNUSED,
+                                             Eina_Array *a_in)
+{
+  fprintf(stdout, "_test_object_method_array_of_lists_of_ints(%p)\n", a_in);
+  if (a_in) return a_in;
+  int *v = malloc(sizeof(int));
+  *v = 42;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, eina_list_append(NULL, v));
+  return arr;
+}
+
+EOLIAN static Eina_List *
+_test_object_method_list_of_arrays_of_ints(Eo* obj EINA_UNUSED,
+                                             Test_Object_Data *pd EINA_UNUSED,
+                                             Eina_List *l_in)
+{
+  fprintf(stdout, "_test_object_method_list_of_arrays_of_ints(%p)\n", l_in);
+  if (l_in) return l_in;
+  int *v = malloc(sizeof(int));
+  *v = 42;
+  Eina_Array *arr = eina_array_new(2);
+  eina_array_push(arr, v);
+  return eina_list_append(NULL, arr);
+}
+
+EOLIAN static const Eina_List *
+_test_object_method_list_with_opaque_elements(Eo* obj EINA_UNUSED,
+                                                Test_Object_Data *pd EINA_UNUSED)
+{
+  fprintf(stdout, "_test_object_method_list_with_opaque_elements()\n");
+  return NULL;
+}
+
+EOLIAN static Test_Enum_Ex
+_test_object_method_in_enum_return_enum(Eo* obj EINA_UNUSED,
+                                          Test_Object_Data *pd EINA_UNUSED,
+                                          Test_Enum_Ex e)
+{
+  fprintf(stdout, "_test_object_method_in_enum_return_enum(%d)\n", e);
+  return e;
+}
+
+EOLIAN static Test_Struct_Ex *
+_test_object_method_in_struct_return_struct(Eo* obj EINA_UNUSED,
+                                     Test_Object_Data *pd EINA_UNUSED,
+                                     Test_Struct_Ex *s)
+{
+  fprintf(stdout, "_test_object_method_in_struct_return_struct()\n");
+  return s;
+}
+
+EOLIAN static void
+_test_object_event_repeated_event_name(Eo* obj EINA_UNUSED,
+                                         Test_Object_Data *pd EINA_UNUSED)
+{
+}
+
+#include <test_object.eo.c>
diff --git a/src/tests/eolian_js/test_object.eo b/src/tests/eolian_js/test_object.eo
new file mode 100644 (file)
index 0000000..c292c24
--- /dev/null
@@ -0,0 +1,305 @@
+enum Test.Enum_Ex {
+     first = 0,
+     second,
+     third,
+     fourth
+}
+
+struct Test.Struct_Ex {
+    value_int: int;
+    value_enum: Test.Enum_Ex;
+}
+
+class Test.Object (Eo.Base) {
+   legacy_prefix: null;
+   methods {
+       method_integral_in_a {
+           [[ tests integral in ]]
+           params { a: int; }
+       }
+       method_integral_out_a {
+           [[ tests integral out ]]
+           params { @out a: int; }
+       }
+       method_integral_inout {
+           [[ tests integral inout ]]
+           params { @inout a: int; }
+       }
+       method_integral_return_a {
+           [[ tests integral result ]]
+           return: int;
+       }
+       method_div_mod {
+           [[ tests mixed in, outs and result ]]
+           params {
+               a: int;
+               b: int;
+               @out quotient: int;
+               @out remainder: int;
+           }
+           return: bool;
+       }
+       method_and {
+           [[ tests boolean ]]
+           params {
+               a: bool;
+               b: bool;
+           }
+           return: bool;
+       }
+       method_modf {
+           [[ tests floating point ]]
+           params {
+               a: double;
+               @out int_part: double;
+           }
+           return: double;
+       }
+       method_uppercase {
+           [[ tests string ]]
+           params {
+               @inout str: char*;
+           }
+       }
+       method_in_null {
+           [[ tests null input ]]
+           params {
+               a: char*;
+           }
+           return: bool;
+       }
+       method_out_null {
+           [[ tests null output ]]
+           params {
+               @out a: char*;
+           }
+           return: bool;
+       }
+       method_inout_null {
+           [[ tests null output ]]
+           params {
+               @inout a: char*;
+           }
+           return: bool;
+       }
+       method_return_null {
+           [[ tests null return ]]
+           return: char*;
+       }
+       method_null {
+           [[ tests null values ]]
+           params {
+               in: char*;
+               @out out: char*;
+               @inout inout: char*;
+           }
+           return: char*;
+       }
+       method_array_at {
+           [[ tests array ]]
+           params {
+               array: array<int>*;
+               index: int;
+           }
+           return: int;
+       }
+       method_array_with_42 {
+           [[ tests parameters ]]
+           return: free(own(array<int> *), eina_array_free) @warn_unused;
+       }
+       method_array_in_array_out {
+           [[ tests parameters ]]
+           params {
+               @in a_in: array<int> *;
+               @out a_out: array<int> *;
+           }
+       }
+       method_array_of_objects {
+           params {
+               @in a_in: array<Test.Object *> *;
+           }
+           return: array<Test.Object *> *;
+       }
+       method_array_of_strings {
+           params {
+               @in a_in: array<const(char) *> *;
+           }
+           return: array<const(char) *> *;
+       }
+       method_array_of_ints {
+           params {
+               @in a_in: array<int> *;
+           }
+           return: array<int> *;
+       }
+       method_array_of_bools {
+           params {
+               @in a_in: array<bool> *;
+           }
+           return: array<bool> *;
+       }
+       method_array_of_doubles {
+           params {
+               @in a_in: array<double> *;
+           }
+           return: array<double> *;
+       }
+       method_array_of_enums {
+           params {
+               @in a_in: array<Test.Enum_Ex> *;
+           }
+           return: array<Test.Enum_Ex> *;
+       }
+       method_array_of_structs {
+           params {
+               @in a_in: array<Test.Struct_Ex> *;
+           }
+           return: array<Test.Struct_Ex> *;
+       }
+       method_list_with_42 {
+           [[ tests parameters ]]
+           return: free(own(list<int> *), eina_list_free) @warn_unused;
+       }
+       method_list_in_list_out {
+           [[ tests parameters ]]
+           params {
+               @in l_in: list<int> *;
+               @out l_out: list<int> *;
+           }
+       }
+       method_list_of_objects {
+           params {
+               @in l_in: list<Test.Object *> *;
+           }
+           return: list<Test.Object *> *;
+       }
+       method_list_of_strings {
+           params {
+               @in l_in: list<const(char) *> *;
+           }
+           return: list<const(char) *> *;
+       }
+       method_list_of_ints {
+           params {
+               @in l_in: list<int> *;
+           }
+           return: list<int> *;
+       }
+       method_list_of_bools {
+           params {
+               @in l_in: list<bool> *;
+           }
+           return: list<bool> *;
+       }
+       method_list_of_doubles {
+           params {
+               @in l_in: list<double> *;
+           }
+           return: list<double> *;
+       }
+       method_list_of_enums {
+           params {
+               @in l_in: list<Test.Enum_Ex> *;
+           }
+           return: list<Test.Enum_Ex> *;
+       }
+       method_list_of_structs {
+           params {
+               @in l_in: list<Test.Struct_Ex> *;
+           }
+           return: list<Test.Struct_Ex> *;
+       }
+       method_accessor_of_objects {
+           params {
+               @in a_in: accessor<Test.Object *> *;
+           }
+           return: accessor<Test.Object *> *;
+       }
+       method_accessor_of_strings {
+           params {
+               @in a_in: accessor<const(char) *> *;
+           }
+           return: accessor<const(char) *> *;
+       }
+       method_accessor_of_ints {
+           params {
+               @in a_in: accessor<int> *;
+           }
+           return: accessor<int> *;
+       }
+       method_accessor_of_bools {
+           params {
+               @in a_in: accessor<bool> *;
+           }
+           return: accessor<bool> *;
+       }
+       method_accessor_of_doubles {
+           params {
+               @in a_in: accessor<double> *;
+           }
+           return: accessor<double> *;
+       }
+       method_accessor_of_enums {
+           params {
+               @in a_in: accessor<Test.Enum_Ex> *;
+           }
+           return: accessor<Test.Enum_Ex> *;
+       }
+       method_accessor_of_structs {
+           params {
+               @in a_in: accessor<Test.Struct_Ex> *;
+           }
+           return: accessor<Test.Struct_Ex> *;
+       }
+       method_array_of_arrays_of_ints {
+           params {
+               @in a_in: array<array<int> *> *;
+           }
+           return: array<array<int> *> *;
+       }
+       method_list_of_lists_of_ints {
+           params {
+               @in l_in: list<list<int> *> *;
+           }
+           return: list<list<int> *> *;
+       }
+       method_array_of_lists_of_ints {
+           params {
+               @in a_in: array<list<int> *> *;
+           }
+           return: array<list<int> *> *;
+       }
+       method_list_of_arrays_of_ints {
+           params {
+               @in l_in: list<array<int> *> *;
+           }
+           return: list<array<int> *> *;
+       }
+       method_list_with_opaque_elements {
+           return: const(list<Elm.Calendar.Mark*>)*;
+       }
+       method_in_enum_return_enum {
+           params { e: Test.Enum_Ex; }
+           return: Test.Enum_Ex;
+       }
+       method_in_struct_return_struct {
+           params { e: Test.Struct_Ex *; }
+           return: Test.Struct_Ex *;
+       }
+       call_event {
+       }
+       event_repeated_event_name {
+       }
+   }
+   implements {
+      Eo.Base.finalize;
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+   }
+   events {
+      test;
+      test,structarg: Test.Struct_Ex;
+      test,stringarg: const(char)*;
+      repeated,event,name;
+   }
+}