changeset 36:9af360f34c7d

Misc: use raw duktape API
author David Demelier <markand@malikania.fr>
date Wed, 10 Aug 2016 14:30:51 +0200
parents 8e1241156034
children 702e0a2b9e5e
files client/main.cpp libclient/CMakeLists.txt libclient/malikania/animation.hpp libclient/malikania/animator.hpp libclient/malikania/client-target.hpp libclient/malikania/font.hpp libclient/malikania/image.hpp libclient/malikania/js-animation.cpp libclient/malikania/js-animation.hpp libclient/malikania/js-animator.cpp libclient/malikania/js-animator.hpp libclient/malikania/js-client-resources-loader.cpp libclient/malikania/js-client-resources-loader.hpp libclient/malikania/js-client-target.cpp libclient/malikania/js-client-target.hpp libclient/malikania/js-client.cpp libclient/malikania/js-client.hpp libclient/malikania/js-color.cpp libclient/malikania/js-color.hpp libclient/malikania/js-font.cpp libclient/malikania/js-font.hpp libclient/malikania/js-image.cpp libclient/malikania/js-image.hpp libclient/malikania/js-line.cpp libclient/malikania/js-line.hpp libclient/malikania/js-point.cpp libclient/malikania/js-point.hpp libclient/malikania/js-rectangle.cpp libclient/malikania/js-rectangle.hpp libclient/malikania/js-size.cpp libclient/malikania/js-size.hpp libclient/malikania/js-sprite.cpp libclient/malikania/js-sprite.hpp libclient/malikania/js-window.cpp libclient/malikania/js-window.hpp libclient/malikania/sprite.cpp libclient/malikania/sprite.hpp libclient/malikania/window.hpp libcommon/CMakeLists.txt libcommon/malikania/duktape.hpp libcommon/malikania/elapsed-timer.hpp libcommon/malikania/js-elapsed-timer.cpp libcommon/malikania/js-elapsed-timer.hpp libcommon/malikania/js-resources-loader.cpp libcommon/malikania/js-resources-loader.hpp libcommon/malikania/js.hpp tests/libclient/js-animation/main.cpp tests/libclient/js-color/main.cpp tests/libclient/js-font/main.cpp tests/libclient/js-image/main.cpp tests/libclient/js-line/main.cpp tests/libclient/js-point/main.cpp tests/libclient/js-rectangle/main.cpp tests/libclient/js-size/main.cpp tests/libclient/js-sprite/main.cpp tests/libclient/js-window/main.cpp tests/libcommon/js-elapsed-timer/main.cpp
diffstat 57 files changed, 3091 insertions(+), 4876 deletions(-) [+]
line wrap: on
line diff
--- a/client/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/client/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -37,6 +37,8 @@
 #include <malikania/js-sprite.hpp>
 #include <malikania/js-window.hpp>
 
+#if 0
+
 using namespace malikania;
 
 namespace {
@@ -208,3 +210,8 @@
 
     return 0;
 }
+
+#endif
+
+int main() {}
+
--- a/libclient/CMakeLists.txt	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
@@ -31,6 +31,7 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-animation.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-animator.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client.hpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client-resources-loader.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client-target.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-color.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-font.hpp
@@ -65,6 +66,7 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-animation.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-animator.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client-resources-loader.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client-target.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-color.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-font.cpp
--- a/libclient/malikania/animation.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/animation.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -29,7 +29,6 @@
 #include <memory>
 #include <vector>
 
-#include "js.hpp"
 #include "sprite.hpp"
 
 namespace malikania {
@@ -87,7 +86,7 @@
  *
  * \see Animator
  */
-class Animation : public duk::Bindable {
+class Animation {
 private:
     Sprite m_sprite;
     AnimationFrames m_frames;
--- a/libclient/malikania/animator.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/animator.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -25,7 +25,6 @@
  */
 
 #include "elapsed-timer.hpp"
-#include "js.hpp"
 
 namespace malikania {
 
@@ -39,7 +38,7 @@
  *
  * The animator contains an animation and a state.
  */
-class Animator : public duk::Bindable {
+class Animator {
 private:
     Animation &m_animation;
     ElapsedTimer m_timer;
--- a/libclient/malikania/client-target.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/client-target.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -23,7 +23,7 @@
 
 namespace malikania {
 
-class Client::Target : public duk::Bindable {
+class Client::Target {
 public:
     Target() = default;
 
--- a/libclient/malikania/font.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/font.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -27,7 +27,6 @@
 #include <memory>
 #include <string>
 
-#include "js.hpp"
 #include "size.hpp"
 
 namespace malikania {
@@ -36,7 +35,7 @@
  * \class Font
  * \brief Font object.
  */
-class Font : public duk::Bindable {
+class Font {
 private:
     class Backend;
 
--- a/libclient/malikania/image.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/image.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -27,7 +27,6 @@
 #include <memory>
 #include <string>
 
-#include "js.hpp"
 #include "point.hpp"
 #include "rectangle.hpp"
 #include "size.hpp"
@@ -40,7 +39,7 @@
  * \class Image
  * \brief Image object.
  */
-class Image : public duk::Bindable {
+class Image {
 private:
     class Backend;
 
--- a/libclient/malikania/js-animation.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-animation.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,42 +16,89 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "client-resources-loader.hpp"
+#include <cassert>
+
+#include "js-client-resources-loader.hpp"
 #include "js-animation.hpp"
 
 namespace malikania {
 
 namespace {
 
-duk::Ret constructor(duk::ContextPtr ctx)
+const std::string Signature("\xff""\xff""malikania-animation-ptr");
+
+duk_ret_t constructor(duk_context *ctx)
 {
-    duk::StackAssert sa(ctx);
-
     if (!duk_is_constructor_call(ctx))
-        duk::raise(ctx, DUK_ERR_ERROR, "animation must be new-constructed");
+        duk_error(ctx, DUK_ERR_ERROR, "animation must be new-constructed");
 
     try {
-        auto loader = duk::getGlobal<ClientResourcesLoader *>(ctx, "\xff""\xff""loader");
-        auto animation = loader->loadAnimation(duk::require<std::string>(ctx, 0));
+        auto loader = dukx_get_client_loader(ctx);
+        auto animation = loader->loadAnimation(duk_require_string(ctx, 0));
+
+        dukx_new_animation(ctx, new Animation(std::move(animation)));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
 
-        duk::construct(ctx, std::make_shared<Animation>(std::move(animation)));
-    } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
+    return 0;
+}
+
+duk_ret_t destructor(duk_context *ctx)
+{
+    duk_get_prop_string(ctx, 0, Signature.c_str());
+    delete static_cast<Animation *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+    duk_del_prop_string(ctx, 0, Signature.c_str());
 
     return 0;
 }
 
 } // !namespace
 
-void loadMalikaniaAnimation(duk::ContextPtr ctx)
+void dukx_new_animation(duk_context *ctx, Animation *animation)
 {
-    duk::StackAssert sa(ctx);
+    assert(ctx);
+    assert(animation);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, animation);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+}
+
+Animation *dukx_require_animation(duk_context *ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::push(ctx, duk::Function{constructor, 1});
-    duk::putProperty(ctx, -2, "Animation");
-    duk::pop(ctx);
+    duk_get_prop_string(ctx, index, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animation object");
+
+    return static_cast<Animation *>(ptr);
+}
+
+void dukx_load_animation(duk_context *ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_push_c_function(ctx, destructor, 1);
+    duk_set_finalizer(ctx, -2);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Animation");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-animation.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-animation.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,12 +19,39 @@
 #ifndef MALIKANIA_JS_ANIMATION_HPP
 #define MALIKANIA_JS_ANIMATION_HPP
 
+#include <malikania/duktape.hpp>
+
 #include "animation.hpp"
-#include "js.hpp"
 
 namespace malikania {
 
-void loadMalikaniaAnimation(duk::ContextPtr ctx);
+/**
+ * Construct an Animation object as this.
+ *
+ * \pre ctx != nullptr
+ * \pre animation != nullptr
+ * \param ctx the context
+ * \param animation the animation
+ */
+void dukx_new_animation(duk_context *ctx, Animation *animation);
+
+/**
+ * Get an Animation object at the given index or raise a JavaScript error.
+ *
+ * \pre ctx != nullptr
+ * \param ctx the context
+ * \param index the value index
+ * \return the Animation object
+ */
+Animation *dukx_require_animation(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Load the Animation module into the context.
+ *
+ * \pre ctx != nullptr
+ * \param ctx the context
+ */
+void dukx_load_animation(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/js-animator.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-animator.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,6 +16,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cassert>
+#include <string>
+
 #include "js-animation.hpp"
 #include "js-animator.hpp"
 #include "js-point.hpp"
@@ -25,61 +28,117 @@
 
 namespace {
 
-duk::Ret constructor(duk::ContextPtr ctx)
+const std::string Signature("\xff""\xff""malikania-animator-ptr");
+
+Animator *self(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
+
+    return static_cast<Animator *>(ptr);
+}
+
+duk_ret_t constructor(duk_context *ctx)
 {
     if (!duk_is_constructor_call(ctx))
-        duk::raise(ctx, DUK_ERR_ERROR, "animator must be new-constructed");
-
-    duk::construct(ctx, std::make_shared<Animator>(*duk::require<std::shared_ptr<Animation>>(ctx, 0)));
+        duk_error(ctx, DUK_ERR_ERROR, "animator must be new-constructed");
 
     // Be sure animation get not collected before.
-    duk::push(ctx, duk::This());
-    duk::dup(ctx, 0);
-    duk::putProperty(ctx, -2, "\xff""\xff""animation-ref");
+    dukx_new_animator(ctx, new Animator(*dukx_require_animation(ctx, 0)));
+    duk_push_this(ctx);
+    duk_dup(ctx, 0);
+    duk_put_prop_string(ctx, -2, "\xff""\xff""animation-ref");
 
     return 0;
 }
 
-duk::Ret draw(duk::ContextPtr ctx)
+duk_ret_t destructor(duk_context *ctx)
+{
+    duk_get_prop_string(ctx, 0, Signature.c_str());
+    delete static_cast<Animator *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+    duk_del_prop_string(ctx, 0, Signature.c_str());
+
+    return 0;
+}
+
+duk_ret_t draw(duk_context *ctx)
 {
     try {
-        auto self = duk::self<std::shared_ptr<Animator>>(ctx);
-        auto window = duk::get<std::shared_ptr<Window>>(ctx, 0);
-        auto point = duk::get<Point>(ctx, 1);
-
-        self->draw(*window, point);
+        self(ctx)->draw(*dukx_require_window(ctx, 0), dukx_get_point(ctx, 1));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret update(duk::ContextPtr ctx)
+duk_ret_t update(duk_context *ctx)
 {
-    duk::self<std::shared_ptr<Animator>>(ctx)->update();
+    self(ctx)->update();
 
     return 0;
 }
 
-const duk::FunctionMap methods{
-    { "draw",   { draw, 2 } },
-    { "update", { update, 0 } }
+const duk_function_list_entry methods[] = {
+    { "draw",   draw,       2 },
+    { "update", update,     0 },
+    { nullptr,  nullptr,    0 }
 };
 
 } // !namespace
 
-void loadMalikaniaAnimator(duk::ContextPtr ctx)
+void dukx_new_animator(duk_context *ctx, Animator *animator)
 {
-    duk::StackAssert sa(ctx);
+    assert(ctx);
+    assert(animator);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, animator);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+}
+
+Animator *dukx_require_animator(duk_context *ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::push(ctx, duk::Function{constructor, 1});
-    duk::push(ctx, duk::Object());
-    duk::put(ctx, methods);
-    duk::putProperty(ctx, -2, "prototype");
-    duk::putProperty(ctx, -2, "Animator");
-    duk::pop(ctx);
+    duk_get_prop_string(ctx, index, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
+
+    return static_cast<Animator *>(ptr);
+}
+
+void dukx_load_animator(duk_context *ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_push_c_function(ctx, destructor, 1);
+    duk_set_finalizer(ctx, -2);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Animator");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-animator.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-animator.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -20,11 +20,31 @@
 #define MALIKANIA_JS_ANIMATOR_HPP
 
 #include "animator.hpp"
-#include "js.hpp"
+#include "duktape.hpp"
 
 namespace malikania {
 
-void loadMalikaniaAnimator(duk::ContextPtr ctx);
+/**
+ * Construct an Animator object as this.
+ *
+ * \pre ctx != nullptr
+ * \pre animator != nullptr
+ * \param ctx the context
+ * \param animator the animator
+ */
+void dukx_new_animator(duk_context *ctx, Animator *animator);
+
+/**
+ * Get the animator at the given index.
+ *
+ * \pre ctx != nullptr
+ * \param ctx the context
+ * \param index the value index
+ * \return the animator
+ */
+Animator *dukx_require_animator(duk_context *ctx, duk_idx_t index);
+
+void dukx_load_animator(duk_context *ctx);
 
 } // !malikania
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/js-client-resources-loader.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -0,0 +1,59 @@
+/*
+ * js-client-resources-loader.cpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cassert>
+
+#include "js-client-resources-loader.hpp"
+#include "js-resources-loader.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Variable("\xff""\xff""malikania-client-resources-loader");
+
+} // !namespace
+
+void dukx_put_client_loader(duk_context *ctx, ClientResourcesLoader *loader)
+{
+    assert(ctx);
+    assert(loader);
+
+    // Also store as parent.
+    dukx_put_loader(ctx, loader);
+
+    StackAssert sa(ctx);
+
+    duk_push_pointer(ctx, loader);
+    duk_put_global_string(ctx, Variable.c_str());
+}
+
+ClientResourcesLoader *dukx_get_client_loader(duk_context *ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, Variable.c_str());
+    auto ptr = static_cast<ClientResourcesLoader *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+
+    return static_cast<ClientResourcesLoader *>(ptr);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/js-client-resources-loader.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -0,0 +1,33 @@
+/*
+ * js-client-resources-loader.hpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
+#define MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
+
+#include "client-resources-loader.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
+
+void dukx_put_client_loader(duk_context *ctx, ClientResourcesLoader *);
+
+ClientResourcesLoader *dukx_get_client_loader(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
--- a/libclient/malikania/js-client-target.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-client-target.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -1,3 +1,21 @@
+/*
+ * js-client-target.cpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
 #include "js-client-target.hpp"
 
 namespace malikania {
@@ -9,32 +27,29 @@
 
 namespace {
 
-duk::Ret constructor(duk::ContextPtr ctx)
+duk_ret_t constructor(duk_context *ctx)
 {
-
-
     return 0;
 }
 
-duk::Ret draw(duk::ContextPtr ctx)
+duk_ret_t draw(duk_context *ctx)
 {
-    //duk::self<std::shared_ptr<Client::Target>>(ctx)->draw();
-
     return 0;
 }
 
 } // !namespace
 
-void loadMalikaniaClientTarget(duk::ContextPtr ctx)
+void dukx_load_client_target(duk_context *ctx)
 {
-    duk::StackAssert sa(ctx);
+    StackAssert sa(ctx);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::getProperty<void>(ctx, -1, "Client");
-    duk::push(ctx, duk::Function{constructor});
-    duk::putProperty(ctx, -1, "prototype", duk::Object());
-    duk::putProperty(ctx, -2, "Target");
-    duk::pop(ctx, 2);
+    duk_get_global_string(ctx, "Malikania");
+    duk_get_prop_string(ctx, -1, "Client");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_prop_string(ctx, -1, "prototype");
+    duk_put_prop_string(ctx, -2, "Target");
+    duk_pop_2(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-client-target.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-client-target.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -1,12 +1,30 @@
+/*
+ * js-client-target.hpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
 #ifndef MALIKANIA_JS_CLIENT_TARGET_HPP
 #define MALIKANIA_JS_CLIENT_TARGET_HPP
 
 #include "client-target.hpp"
-#include "js.hpp"
+#include "duktape.hpp"
 
 namespace malikania {
 
-void loadMalikaniaClientTarget(duk::ContextPtr ctx);
+void dukx_load_client_target(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/js-client.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-client.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -1,3 +1,23 @@
+/*
+ * js-client.cpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cassert>
+
 #include "js-client.hpp"
 #include "js-client-target.hpp"
 #include "js-window.hpp"
@@ -6,48 +26,56 @@
 
 namespace {
 
-duk::Ret draw(duk::ContextPtr ctx)
+duk_ret_t draw(duk_context *)
 {
+#if 0
     try {
         duk::self<std::shared_ptr<Client>>(ctx)->draw();
     } catch (const std::exception &ex) {
         duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
+#endif
 
     return 0;
 }
 
-duk::Ret setTarget(duk::ContextPtr ctx)
+duk_ret_t setTarget(duk_context *)
 {
-    auto self = duk::self<std::shared_ptr<Client>>(ctx);
+#if 0
+    auto self = duk::self<Client *>(ctx);
     auto target = duk::get<std::shared_ptr<Client::Target>>(ctx, 0);
 
     self->setTarget(std::move(target));
+#endif
 
     return 0;
 }
 
-duk::Ret update(duk::ContextPtr ctx)
+duk_ret_t update(duk_context *)
 {
+#if 0
     try {
         duk::self<std::shared_ptr<Client>>(ctx)->update();
     } catch (const std::exception &ex) {
         duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
+#endif
 
     return 0;
 }
 
-const duk::FunctionMap methods{
-    { "draw",       { draw,         0 } },
-    { "setTarget",  { setTarget,    1 } },
-    { "update",     { update,       0 } }
+const duk_function_list_entry methods[] = {
+    { "draw",       draw,       0 },
+    { "setTarget",  setTarget,  1 },
+    { "update",     update,     0 },
+    { nullptr,      nullptr,    0 }
 };
 
 } // !namespace
 
-void loadMalikaniaClient(duk::ContextPtr ctx)
+void dukx_load_client(duk_context *ctx)
 {
+#if 0
     duk::StackAssert sa(ctx);
 
     duk::getGlobal<void>(ctx, "Malikania");
@@ -59,6 +87,7 @@
     duk::putProperty(ctx, -2, "prototype");
     duk::putProperty(ctx, -2, "Client");
     duk::pop(ctx);
+#endif
 }
 
 } // !malikania
--- a/libclient/malikania/js-client.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-client.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -1,31 +1,30 @@
+/*
+ * js-client.hpp -- client resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
 #ifndef MALIKANIA_JS_CLIENT_HPP
 #define MALIKANIA_JS_CLIENT_HPP
 
 #include "client.hpp"
-#include "js.hpp"
+#include "duktape.hpp"
 
 namespace malikania {
 
-namespace duk {
-
-template <>
-class TypeTraits<Client> {
-public:
-    static inline void prototype(ContextPtr ctx)
-    {
-        StackAssert sa(ctx, 1);
-
-        getGlobal<void>(ctx, "Malikania");
-        getProperty<void>(ctx, -1, "Client");
-        getProperty<void>(ctx, -1, "prototype");
-        remove(ctx, -2);
-        remove(ctx, -2);
-    }
-};
-
-} // !duk
-
-void loadMalikaniaClient(duk::ContextPtr ctx);
+void dukx_load_client(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/js-color.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-color.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -25,11 +25,11 @@
 
 namespace {
 
-std::uint8_t clampComponent(duk::ContextPtr ctx, int value, bool required)
+std::uint8_t clampComponent(duk_context *ctx, int value, bool required)
 {
     if (value < 0 || value > 255) {
         if (required)
-            duk::raise(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range (0, 255)", value);
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range (0, 255)", value);
         else
             value = util::clamp(value, 0, 255);
     }
@@ -37,46 +37,53 @@
     return static_cast<std::uint8_t>(value);
 }
 
-Color parseString(duk::ContextPtr ctx, duk::Index index, bool required)
+Color parseString(duk_context *ctx, duk_idx_t index, bool required)
 {
-    assert(duk::type(ctx, index) == DUK_TYPE_STRING);
+    assert(duk_is_string(ctx, index));
 
     Color color;
 
     try {
-        color = Color(duk::get<std::string>(ctx, index));
+        color = Color(duk_get_string(ctx, index));
     } catch (const std::exception &ex) {
-        if (required) {
-            duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
-        }
+        if (required)
+            duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return color;
 }
 
-Color parseObject(duk::ContextPtr ctx, duk::Index index, bool required)
+Color parseObject(duk_context *ctx, duk_idx_t index, bool required)
 {
-    assert(duk::type(ctx, index) == DUK_TYPE_OBJECT);
+    assert(duk_is_object(ctx, index));
+
+    auto require = [&] (const auto prop) -> std::uint8_t {
+        if (required && !duk_has_prop_string(ctx, index, prop))
+            duk_error(ctx, DUK_ERR_ERROR, "missing %s property in color description", prop);
 
-    auto require = [&] (const std::string &property) -> std::uint8_t {
-        if (required && !duk::hasProperty(ctx, index, property)) {
-            duk::raise(ctx, DUK_ERR_ERROR, "missing %s property in color description", property.c_str());
-        }
+        duk_get_prop_string(ctx, index, prop);
+        auto comp = duk_get_int(ctx, -1);
+        duk_pop(ctx);
 
-        return clampComponent(ctx, duk::getProperty<int>(ctx, index, property), required);
+        return clampComponent(ctx, comp, required);
     };
 
+    // Alpha is optional.
+    duk_get_prop_string(ctx, index, "alpha");
+    auto alpha = duk_is_number(ctx, -1) ? duk_to_int(ctx, -1) : 255;
+    duk_pop(ctx);
+
     return Color(
         require("red"),
         require("green"),
         require("blue"),
-        clampComponent(ctx, duk::optionalProperty<int>(ctx, index, "alpha", 255), required)
+        clampComponent(ctx, alpha, required)
     );
 }
 
-Color parse(duk::ContextPtr ctx, duk::Index index, bool required, Color color = {})
+Color parse(duk_context *ctx, duk_idx_t index, bool required, Color color = {})
 {
-    switch (duk::type(ctx, index)) {
+    switch (duk_get_type(ctx, index)) {
     case DUK_TYPE_STRING:
         color = parseString(ctx, index, required);
         break;
@@ -85,7 +92,7 @@
         break;
     default:
         if (required)
-            duk::raise(ctx, DUK_ERR_TYPE_ERROR, "color (string, object) expected");
+            duk_error(ctx, DUK_ERR_TYPE_ERROR, "color (string, object) expected");
 
         break;
     }
@@ -93,35 +100,37 @@
     return color;
 }
 
-duk::Ret constructor(duk::ContextPtr ctx)
+duk_ret_t constructor(duk_context *ctx)
 {
     Color color;
 
     /*
-     * The constructor allows an additional signature that takes 4 number arguments, otherwise use the literal
-     * parsing functions.
+     * The constructor allows an additional signature that takes 4 number
+     * arguments, otherwise use the literal parsing functions.
      */
-    if (duk::top(ctx) >= 3) {
+    if (duk_get_top(ctx) >= 3) {
+        // Alpha is optional.
+        auto alpha = duk_is_number(ctx, 3) ? duk_to_int(ctx, 3) : 255;
+
         color = Color(
-            clampComponent(ctx, duk::require<int>(ctx, 0), true),
-            clampComponent(ctx, duk::require<int>(ctx, 1), true),
-            clampComponent(ctx, duk::require<int>(ctx, 2), true),
-            clampComponent(ctx, duk::optional<int>(ctx, 3, 255), true)
+            clampComponent(ctx, duk_require_int(ctx, 0), true),
+            clampComponent(ctx, duk_require_int(ctx, 1), true),
+            clampComponent(ctx, duk_require_int(ctx, 2), true),
+            clampComponent(ctx, alpha, true)
         );
-    } else if (duk::top(ctx) == 1)
+    } else if (duk_get_top(ctx) == 1)
         color = parse(ctx, 0, true);
 
-    duk::Ret ret;
+    duk_ret_t ret;
 
     // Allow both constructor and non constructor calls.
     if (duk_is_constructor_call(ctx)) {
-        duk::push(ctx, duk::This());
-        /* TODO: use duk::put when available */
-        duk::TypeTraits<Color>::put(ctx, color);
-        duk::pop(ctx);
+        duk_push_this(ctx);
+        dukx_put_color(ctx, color);
+        duk_pop(ctx);
         ret = 0;
     } else {
-        duk::push(ctx, color);
+        dukx_push_color(ctx, color);
         ret = 1;
     }
 
@@ -130,53 +139,53 @@
 
 } //! namespace
 
-namespace duk {
-
-Color TypeTraits<Color>::get(ContextPtr ctx, Index index)
+Color dukx_get_color(duk_context *ctx, duk_idx_t index)
 {
     return parse(ctx, index, false);
 }
 
-Color TypeTraits<Color>::require(ContextPtr ctx, Index index)
+Color dukx_require_color(duk_context *ctx, duk_idx_t index)
 {
     return parse(ctx, index, true);
 }
 
-Color TypeTraits<Color>::optional(ContextPtr ctx, Index index, Color def)
+Color dukx_optional_color(duk_context *ctx, duk_idx_t index, Color def)
 {
     return parse(ctx, index, false, std::move(def));
 }
 
-void TypeTraits<Color>::push(ContextPtr ctx, const Color &color)
+void dukx_push_color(duk_context *ctx, const Color &color)
 {
-    duk::StackAssert sa(ctx, 1);
+    StackAssert sa(ctx, 1);
 
-    duk::push(ctx, Object());
-    /* TODO: use duk::put when available */
-    duk::TypeTraits<Color>::put(ctx, color);
+    duk_push_object(ctx);
+    dukx_put_color(ctx, color);
 }
 
-void TypeTraits<Color>::put(ContextPtr ctx, const Color &color)
+void dukx_put_color(duk_context *ctx, const Color &color)
 {
-    assert(type(ctx, -1) == DUK_TYPE_OBJECT);
+    assert(duk_is_object(ctx, -1));
 
     StackAssert sa(ctx, 0);
 
-    putProperty(ctx, -1, "red", static_cast<int>(color.red()));
-    putProperty(ctx, -1, "green", static_cast<int>(color.green()));
-    putProperty(ctx, -1, "blue", static_cast<int>(color.blue()));
-    putProperty(ctx, -1, "alpha", static_cast<int>(color.alpha()));
+    duk_push_uint(ctx, color.red());
+    duk_put_prop_string(ctx, -2, "red");
+    duk_push_uint(ctx, color.green());
+    duk_put_prop_string(ctx, -2, "green");
+    duk_push_uint(ctx, color.blue());
+    duk_put_prop_string(ctx, -2, "blue");
+    duk_push_uint(ctx, color.alpha());
+    duk_put_prop_string(ctx, -2, "alpha");
 }
 
-} // !duk
-
-void loadMalikaniaColor(duk::ContextPtr ctx)
+void dukx_load_color(duk_context *ctx)
 {
-    duk::StackAssert sa(ctx, 0);
+    StackAssert sa(ctx, 0);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::putProperty(ctx, -1, "Color", duk::Function{constructor, DUK_VARARGS});
-    duk::pop(ctx);
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Color");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-color.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-color.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,14 +19,8 @@
 #ifndef MALIKANIA_JS_COLOR_HPP
 #define MALIKANIA_JS_COLOR_HPP
 
-#include "color.hpp"
-#include "js.hpp"
-
-namespace malikania {
-
-namespace duk {
-
 /**
+ * \file js-color.h
  * \brief JavaScript binding for Color.
  *
  * Colors can be created from plain JavaScript object.
@@ -42,61 +36,61 @@
  *
  * It can also takes strings like "#rrggbbaa" and SVG names.
  */
-template <>
-class TypeTraits<Color> {
-public:
-    /**
-     * Get a color.
-     *
-     * May return a default value or a color with adjusted components.
-     *
-     * \param ctx the context
-     * \param index the index
-     */
-    static Color get(ContextPtr ctx, Index index);
+
+#include "color.hpp"
+#include "duktape.hpp"
+
+namespace malikania {
 
-    /**
-     * Require a color.
-     *
-     * If the color has any invalid component, raise a JavaScript error.
-     *
-     * \param ctx the context
-     * \param index the index
-     */
-    static Color require(ContextPtr ctx, Index index);
+/**
+ * Get a color.
+ *
+ * May return a default value or a color with adjusted components.
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+Color dukx_get_color(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Require a color.
+ *
+ * If the color has any invalid component, raise a JavaScript error.
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+Color dukx_require_color(duk_context *ctx, duk_idx_t index);
 
-    /**
-     * Like get, but return the default value only if the value at the given index is not an object or not a string,
-     * otherwise, adjust invalid values.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \param def the default value
-     */
-    static Color optional(ContextPtr ctx, Index index, Color def);
+/**
+ * Like get, but return the default value only if the value at the given
+ * index is not an object or not a string, otherwise, adjust invalid values.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @param def the default value
+ */
+Color dukx_optional_color(duk_context *ctx, duk_idx_t index, Color def);
 
-    /**
-     * Push the color as object.
-     *
-     * \param ctx the context
-     * \param color the color
-     */
-    static void push(ContextPtr ctx, const Color &color);
+/**
+ * Push the color as object.
+ *
+ * @param ctx the context
+ * @param color the color
+ */
+void dukx_push_color(duk_context *ctx, const Color &color);
 
-    /**
-     * Put the color properties into the object at the top of the stack.
-     *
-     * \pre the top value must be an object
-     * \param ctx the context
-     * \param color the color
-     */
-    static void put(ContextPtr ctx, const Color &color);
-};
+/**
+ * Put the color properties into the object at the top of the stack.
+ *
+ * @pre the top value must be an object
+ * @param ctx the context
+ * @param color the color
+ */
+void dukx_put_color(duk_context *ctx, const Color &color);
 
-} // !duk
-
-void loadMalikaniaColor(duk::ContextPtr ctx);
+void dukx_load_color(duk_context *ctx);
 
 } // !malikania
 
-#endif // !MALIKANIA_JS_COLOR_HPP
\ No newline at end of file
+#endif // !MALIKANIA_JS_COLOR_HPP
--- a/libclient/malikania/js-font.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-font.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,7 +16,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "client-resources-loader.hpp"
+#include <cassert>
+
+#include "js-client-resources-loader.hpp"
 #include "js-font.hpp"
 #include "js-size.hpp"
 
@@ -24,57 +26,104 @@
 
 namespace {
 
-duk::Ret constructor(duk::ContextPtr ctx)
+const std::string Signature("\xff""\xff""malikania-font-ptr");
+
+Font *self(duk_context *ctx)
 {
-    duk::StackAssert sa(ctx);
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Font object");
+
+    return static_cast<Font *>(ptr);
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    StackAssert sa(ctx);
 
     if (!duk_is_constructor_call(ctx))
-        duk::raise(ctx, DUK_ERR_ERROR, "font must be new-constructed");
+        duk_error(ctx, DUK_ERR_ERROR, "font must be new-constructed");
 
     try {
-        auto loader = duk::getGlobal<ClientResourcesLoader *>(ctx, "\xff""\xff""loader");
-        auto id = duk::require<std::string>(ctx, 0);
-        auto size = duk::require<int>(ctx, 1);
+        auto loader = dukx_get_client_loader(ctx);
+        auto id = duk_require_string(ctx, 0);
+        auto size = duk_require_int(ctx, 1);
 
         if (size < 0)
-            duk::raise(ctx, DUK_ERR_RANGE_ERROR, "%d must not be negative", size);
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d must not be negative", size);
 
-        duk::construct(ctx, std::make_shared<Font>(loader->loadFont(id, static_cast<unsigned>(size))));
+        dukx_new_font(ctx, new Font(loader->loadFont(id, static_cast<unsigned>(size))));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret clip(duk::ContextPtr ctx)
+duk_ret_t clip(duk_context *ctx)
 {
     try {
-        duk::push(ctx, duk::self<std::shared_ptr<Font>>(ctx)->clip(duk::require<std::string>(ctx, 0)));
+        dukx_push_size(ctx, self(ctx)->clip(duk_require_string(ctx, 0)));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 1;
 }
 
-const duk::FunctionMap methods{
-    { "clip",    { clip, 1 } }
+const duk_function_list_entry methods[] = {
+    { "clip",   clip,       1 },
+    { nullptr,  nullptr,    0 }
 };
 
 } // !namespace
 
-void loadMalikaniaFont(duk::ContextPtr ctx)
+void dukx_new_font(duk_context *ctx, Font *font)
 {
-    duk::StackAssert sa(ctx);
+    assert(ctx);
+    assert(font);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, font);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+}
+
+Font *dukx_require_font(duk_context *ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::push(ctx, duk::Function{constructor, 2});
-    duk::push(ctx, duk::Object());
-    duk::put(ctx, methods);
-    duk::putProperty(ctx, -2, "prototype");
-    duk::putProperty(ctx, -2, "Font");
-    duk::pop(ctx);
+    duk_get_prop_string(ctx, index, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Font object");
+
+    return static_cast<Font *>(ptr);
+}
+
+void dukx_load_font(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 2);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Font");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-font.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-font.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,12 +19,16 @@
 #ifndef MALIKANIA_JS_FONT_HPP
 #define MALIKANIA_JS_FONT_HPP
 
+#include "duktape.hpp"
 #include "font.hpp"
-#include "js.hpp"
 
 namespace malikania {
 
-void loadMalikaniaFont(duk::ContextPtr ctx);
+void dukx_new_font(duk_context *ctx, Font *font);
+
+Font *dukx_require_font(duk_context *ctx, duk_idx_t index);
+
+void dukx_load_font(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/js-image.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-image.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,7 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "client-resources-loader.hpp"
+#include "js-client-resources-loader.hpp"
 #include "js-image.hpp"
 #include "js-point.hpp"
 #include "js-rectangle.hpp"
@@ -27,76 +27,106 @@
 
 namespace {
 
-duk::Ret size(duk::ContextPtr ctx)
+const std::string Signature("\xff""\xff""malikania-image-ptr");
+
+Image *self(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
+
+    return static_cast<Image *>(ptr);
+}
+
+duk_ret_t size(duk_context *ctx)
 {
     try {
-        duk::push(ctx, duk::self<std::shared_ptr<Image>>(ctx)->size());
+        dukx_push_size(ctx, self(ctx)->size());
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 1;
 }
 
-duk::Ret draw(duk::ContextPtr ctx)
+duk_ret_t draw(duk_context *ctx)
 {
     try {
-        auto self = duk::self<std::shared_ptr<Image>>(ctx);
-        auto window = duk::get<std::shared_ptr<Window>>(ctx, 0);
+        auto image = self(ctx);
+        auto window = dukx_require_window(ctx, 0);
 
-        if (duk::top(ctx) == 2)
-            self->draw(*window, duk::get<Point>(ctx, 1));
-        else if (duk::top(ctx) == 3)
-            self->draw(*window, duk::get<Rectangle>(ctx, 1), duk::get<Rectangle>(ctx, 2));
+        if (duk_get_top(ctx) == 2)
+            image->draw(*window, dukx_get_point(ctx, 1));
+        else if (duk_get_top(ctx) == 3)
+            image->draw(*window, dukx_get_rect(ctx, 1), dukx_get_rect(ctx, 2));
         else
-            duk::raise(ctx, DUK_ERR_TYPE_ERROR, "invalid number of arguments: #%d", duk::top(ctx));
+            duk_error(ctx, DUK_ERR_TYPE_ERROR, "invalid number of arguments: #%d", duk_get_top(ctx));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret constructor(duk::ContextPtr ctx)
+duk_ret_t constructor(duk_context *ctx)
 {
-    if (!duk_is_constructor_call(ctx)) {
-        duk::raise(ctx, DUK_ERR_ERROR, "image must be new-constructed");
-    }
+    if (!duk_is_constructor_call(ctx))
+        duk_error(ctx, DUK_ERR_ERROR, "image must be new-constructed");
 
     try {
-        auto loader = duk::getGlobal<ClientResourcesLoader *>(ctx, "\xff""\xff""loader");
-        auto image = loader->loadImage(duk::require<std::string>(ctx, 0));
+        auto loader = dukx_get_client_loader(ctx);
+        auto image = new Image(loader->loadImage(duk_require_string(ctx, 0)));
 
-        duk::construct(ctx, std::make_shared<Image>(std::move(image)));
-        duk::push(ctx, duk::This());
-        duk::push(ctx, "size");
-        duk::push(ctx, duk::Function{size, 0});
-        duk::defineProperty(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
-        duk::pop(ctx);
+        dukx_new_image(ctx, image);
+        duk_push_this(ctx);
+        duk_push_string(ctx, "size");
+        duk_push_c_function(ctx, size, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+        duk_pop(ctx);
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-const duk::FunctionMap methods{
-    { "draw",    { draw,        DUK_VARARGS } }
+const duk_function_list_entry methods[] = {
+    { "draw",   draw,       DUK_VARARGS },
+    { nullptr,  nullptr,    0           }
 };
 
 } // !namespace
 
-void loadMalikaniaImage(duk::ContextPtr ctx)
+void dukx_new_image(duk_context *ctx, Image *image)
 {
-    duk::StackAssert sa(ctx);
+    assert(ctx);
+    assert(image);
+
+    StackAssert sa(ctx);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::push(ctx, duk::Function{constructor, 1});
-    duk::push(ctx, duk::Object());
-    duk::put(ctx, methods);
-    duk::putProperty(ctx, -2, "prototype");
-    duk::putProperty(ctx, -2, "Image");
-    duk::pop(ctx);
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, image);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+}
+
+void dukx_load_image(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Image");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-image.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-image.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,12 +19,14 @@
 #ifndef MALIKANIA_JS_IMAGE_HPP
 #define MALIKANIA_JS_IMAGE_HPP
 
+#include "duktape.hpp"
 #include "image.hpp"
-#include "js.hpp"
 
 namespace malikania {
 
-void loadMalikaniaImage(duk::ContextPtr ctx);
+void dukx_new_image(duk_context *ctx, Image *image);
+
+void dukx_load_image(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/js-line.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-line.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,37 +16,37 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cassert>
+
 #include "js-line.hpp"
 
 namespace malikania {
 
 namespace {
 
-duk::Ret constructor(duk::ContextPtr ctx)
+duk_ret_t constructor(duk_context *ctx)
 {
     Line line;
 
-    if (duk::top(ctx) == 4) {
+    if (duk_get_top(ctx) == 4) {
         line = Line(
-            duk::get<int>(ctx, 0),
-            duk::get<int>(ctx, 1),
-            duk::get<int>(ctx, 2),
-            duk::get<int>(ctx, 3)
+            duk_get_int(ctx, 0),
+            duk_get_int(ctx, 1),
+            duk_get_int(ctx, 2),
+            duk_get_int(ctx, 3)
         );
-    } else if (duk::top(ctx) == 1)
-        line = duk::require<Line>(ctx, 0);
+    } else if (duk_get_top(ctx) == 1)
+        line = dukx_require_line(ctx, 0);
 
-    duk::Ret ret;
+    duk_ret_t ret;
 
     /* Allow both constructor and non constructor calls */
     if (duk_is_constructor_call(ctx)) {
-        duk::push(ctx, duk::This());
-        /* TODO: use duk::put when available */
-        duk::TypeTraits<Line>::put(ctx, line);
-        duk::pop(ctx);
+        duk_push_this(ctx);
+        dukx_put_line(ctx, line);
         ret = 0;
     } else {
-        duk::push(ctx, line);
+        dukx_push_line(ctx, line);
         ret = 1;
     }
 
@@ -55,38 +55,37 @@
 
 } // !namespace
 
-namespace duk {
-
-Line TypeTraits<Line>::get(ContextPtr ctx, Index index)
+Line dukx_get_line(duk_context *ctx, duk_idx_t index)
 {
-    duk::StackAssert sa(ctx);
+    auto get = [&] (auto name) {
+        StackAssert sa(ctx);
 
-    return Line(
-        duk::getProperty<int>(ctx, index, "x1"),
-        duk::getProperty<int>(ctx, index, "y1"),
-        duk::getProperty<int>(ctx, index, "x2"),
-        duk::getProperty<int>(ctx, index, "y2")
-    );
+        duk_get_prop_string(ctx, index, name);
+        auto v = duk_get_int(ctx, -1);
+        duk_pop(ctx);
+
+        return v;
+    };
+
+    return Line(get("x1"), get("y1"), get("x2"), get("y2"));
 }
 
-Line TypeTraits<Line>::require(ContextPtr ctx, Index index)
+Line dukx_require_line(duk_context *ctx, duk_idx_t index)
 {
-    duk::StackAssert sa(ctx);
+    auto get = [&] (auto prop) {
+        if (!duk_has_prop_string(ctx, index, prop))
+            duk_error(ctx, DUK_ERR_ERROR, "missing %s property in line description", prop);
 
-    auto get = [&] (const std::string &property) -> int {
-        if (!duk::hasProperty(ctx, index, property))
-            duk::raise(ctx, DUK_ERR_ERROR, "missing %s property in line description", property.c_str());
+        duk_get_prop_string(ctx, index, prop);
 
-        duk::getProperty<void>(ctx, index, property);
-
-        if (!duk::is<int>(ctx, -1)) {
-            duk::pop(ctx);
-            duk::raise(ctx, DUK_ERR_TYPE_ERROR, "property %s is not an int", property.c_str());
+        if (!duk_is_number(ctx, -1)) {
+            duk_pop(ctx);
+            duk_error(ctx, DUK_ERR_TYPE_ERROR, "property %s is not an int", prop);
         }
 
-        int value = duk::get<int>(ctx, -1);
+        auto value = duk_to_int(ctx, -1);
 
-        duk::pop(ctx);
+        duk_pop(ctx);
 
         return value;
     };
@@ -94,40 +93,43 @@
     return Line(get("x1"), get("y1"), get("x2"), get("y2"));
 }
 
-Line TypeTraits<Line>::optional(ContextPtr ctx, Index index, Line def)
+Line dukx_optional_line(duk_context *ctx, duk_idx_t index, Line def)
 {
-    return duk::is<duk::Object>(ctx, index) ? get(ctx, index) : def;
+    return duk_is_object(ctx, index) ? dukx_get_line(ctx, index) : def;
 }
 
-void TypeTraits<Line>::push(ContextPtr ctx, const Line &line)
+void dukx_push_line(duk_context *ctx, const Line &line)
 {
-    duk::StackAssert sa(ctx, 1);
+    StackAssert sa(ctx, 1);
 
-    duk::push(ctx, duk::Object());
-    duk::TypeTraits<Line>::put(ctx, line);
+    duk_push_object(ctx);
+    dukx_put_line(ctx, line);
 }
 
-void TypeTraits<Line>::put(ContextPtr ctx, const Line &line)
+void dukx_put_line(duk_context *ctx, const Line &line)
 {
-    assert(duk::is<duk::Object>(ctx, -1));
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx);
 
-    duk::StackAssert sa(ctx);
-
-    duk::putProperty(ctx, -1, "x1", line.x1());
-    duk::putProperty(ctx, -1, "y1", line.y1());
-    duk::putProperty(ctx, -1, "x2", line.x2());
-    duk::putProperty(ctx, -1, "y2", line.y2());
+    duk_push_int(ctx, line.x1());
+    duk_put_prop_string(ctx, -2, "x1");
+    duk_push_int(ctx, line.y1());
+    duk_put_prop_string(ctx, -2, "y1");
+    duk_push_int(ctx, line.x2());
+    duk_put_prop_string(ctx, -2, "x2");
+    duk_push_int(ctx, line.y2());
+    duk_put_prop_string(ctx, -2, "y2");
 }
 
-} // !duk
-
-void loadMalikaniaLine(duk::ContextPtr ctx)
+void dukx_load_line(duk_context *ctx)
 {
-    duk::StackAssert sa(ctx, 0);
+    StackAssert sa(ctx, 0);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::putProperty(ctx, -1, "Line", duk::Function{constructor, DUK_VARARGS});
-    duk::pop(ctx);
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Line");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-line.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-line.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,14 +19,8 @@
 #ifndef MALIKANIA_JS_LINE_HPP
 #define MALIKANIA_JS_LINE_HPP
 
-#include "js.hpp"
-#include "line.hpp"
-
-namespace malikania {
-
-namespace duk {
-
 /**
+ * \file js-line.h
  * \brief JavaScript binding for Line.
  *
  * Lines are plain objects.
@@ -40,59 +34,59 @@
  * }
  * ````
  */
-template <>
-class TypeTraits<Line> {
-public:
-    /**
-     * Get a line.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the line
-     */
-    static Line get(ContextPtr ctx, Index index);
+
+#include "duktape.hpp"
+#include "line.hpp"
+
+namespace malikania {
 
-    /**
-     * Require a line.
-     *
-     * If value is not an object or any property is invalid, raise a JavaScript error.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the line
-     */
-    static Line require(ContextPtr ctx, Index index);
+/**
+ * Get a line.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @return the line
+ */
+Line dukx_get_line(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Require a line.
+ *
+ * If value is not an object or any property is invalid, raise a JavaScript error.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @return the line
+ */
+Line dukx_require_line(duk_context *ctx, duk_idx_t index);
 
-    /**
-     * Like get but return def if the value at the given index is not an object.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \param def the default value
-     * \return the line
-     */
-    static Line optional(ContextPtr ctx, Index index, Line def);
+/**
+ * Like get but return def if the value at the given index is not an object.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @param def the default value
+ * @return the line
+ */
+Line dukx_optional_line(duk_context *ctx, duk_idx_t index, Line def);
 
-    /**
-     * Push the line as object.
-     *
-     * \param ctx the context
-     * \param line the line
-     */
-    static void push(ContextPtr ctx, const Line &line);
+/**
+ * Push the line as object.
+ *
+ * @param ctx the context
+ * @param line the line
+ */
+void dukx_push_line(duk_context *ctx, const Line &line);
 
-    /**
-     * Put the line properties into the object at the top of the stack.
-     *
-     * \param ctx the context
-     * \param line the line
-     */
-    static void put(ContextPtr ctx, const Line &line);
-};
+/**
+ * Put the line properties into the object at the top of the stack.
+ *
+ * @param ctx the context
+ * @param line the line
+ */
+void dukx_put_line(duk_context *ctx, const Line &line);
 
-} // !duk
-
-void loadMalikaniaLine(duk::ContextPtr ctx);
+void dukx_load_line(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/js-point.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-point.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,49 +16,61 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cassert>
+
 #include "js-point.hpp"
 
 namespace malikania {
 
 namespace {
 
-Point parse(duk::ContextPtr ctx, duk::Index index, bool required, Point point = {})
+Point parse(duk_context *ctx, duk_idx_t index, bool required, Point point = {})
 {
-    duk::StackAssert sa(ctx);
+    StackAssert sa(ctx);
+
+    if (duk_is_object(ctx, index)) {
+        if (required && !duk_has_prop_string(ctx, index, "x"))
+            duk_error(ctx, DUK_ERR_ERROR, "missing x property in point description");
+        else if (required && !duk_has_prop_string(ctx, index, "y"))
+            duk_error(ctx, DUK_ERR_ERROR, "missing y property in point description");
 
-    if (duk::type(ctx, index) == DUK_TYPE_OBJECT){
-        if (required && !duk::hasProperty(ctx, index, "x"))
-            duk::raise(ctx, DUK_ERR_ERROR, "missing x property in point description");
-        else if (required && !duk::hasProperty(ctx, index, "y"))
-            duk::raise(ctx, DUK_ERR_ERROR, "missing y property in point description");
+        //point = Point(duk::getProperty<int>(ctx, index, "x"), duk::getProperty<int>(ctx, index, "y"));
+        int x;
+        int y;
 
-        point = Point(duk::getProperty<int>(ctx, index, "x"), duk::getProperty<int>(ctx, index, "y"));
+        duk_get_prop_string(ctx, index, "x");
+        x = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+        duk_get_prop_string(ctx, index, "y");
+        y = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+
+        point = Point(x, y);
     } else if (required)
-        duk::raise(ctx, DUK_ERR_TYPE_ERROR, "point object expected");
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "point object expected");
 
     return point;
 }
 
-duk::Ret constructor(duk::ContextPtr ctx)
+duk_ret_t constructor(duk_context *ctx)
 {
     Point point;
 
-    if (duk::top(ctx) == 2)
-        point = Point(duk::require<int>(ctx, 0), duk::require<int>(ctx, 1));
-    else if (duk::top(ctx) == 1)
+    if (duk_get_top(ctx) == 2)
+        point = Point(duk_require_int(ctx, 0), duk_require_int(ctx, 1));
+    else if (duk_get_top(ctx) == 1)
         point = parse(ctx, 0, true);
 
-    duk::Ret ret;
+    duk_ret_t ret;
 
     // Allow both constructor and non constructor calls.
     if (duk_is_constructor_call(ctx)) {
-        duk::push(ctx, duk::This());
-        /* TODO: use duk::put when available */
-        duk::TypeTraits<Point>::put(ctx, point);
-        duk::pop(ctx);
+        duk_push_this(ctx);
+        dukx_put_point(ctx, point);
+        duk_pop(ctx);
         ret = 0;
     } else {
-        duk::push(ctx, point);
+        dukx_push_point(ctx, point);
         ret = 1;
     }
 
@@ -67,50 +79,49 @@
 
 } // !namespace
 
-namespace duk {
-
-Point TypeTraits<Point>::get(ContextPtr ctx, Index index)
+Point dukx_get_point(duk_context *ctx, duk_idx_t index)
 {
     return parse(ctx, index, false);
 }
 
-Point TypeTraits<Point>::require(ContextPtr ctx, Index index)
+Point dukx_require_point(duk_context *ctx, duk_idx_t index)
 {
     return parse(ctx, index, true);
 }
 
-Point TypeTraits<Point>::optional(ContextPtr ctx, Index index, Point def)
+Point dukx_optional_point(duk_context *ctx, duk_idx_t index, Point def)
 {
     return parse(ctx, index, false, std::move(def));
 }
 
-void TypeTraits<Point>::push(ContextPtr ctx, const Point &point)
+void dukx_push_point(duk_context *ctx, const Point &point)
 {
-    duk::StackAssert sa(ctx, 1);
+    StackAssert sa(ctx, 1);
 
-    duk::push(ctx, duk::Object());
-    duk::TypeTraits<Point>::put(ctx, point);
+    duk_push_object(ctx);
+    dukx_put_point(ctx, point);
 }
 
-void TypeTraits<Point>::put(ContextPtr ctx, const Point &point)
+void dukx_put_point(duk_context *ctx, const Point &point)
 {
-    assert(duk::type(ctx, -1) == DUK_TYPE_OBJECT);
+    assert(duk_is_object(ctx, -1));
 
-    duk::StackAssert sa(ctx);
+    StackAssert sa(ctx);
 
-    duk::putProperty(ctx, -1, "x", point.x());
-    duk::putProperty(ctx, -1, "y", point.y());
+    duk_push_int(ctx, point.x());
+    duk_put_prop_string(ctx, -2, "x");
+    duk_push_int(ctx, point.y());
+    duk_put_prop_string(ctx, -2, "y");
 }
 
-} // !duk
-
-void loadMalikaniaPoint(duk::ContextPtr ctx)
+void dukx_load_point(duk_context *ctx)
 {
-    duk::StackAssert sa(ctx, 0);
+    StackAssert sa(ctx, 0);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::putProperty(ctx, -1, "Point", duk::Function{constructor, DUK_VARARGS});
-    duk::pop(ctx);
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Point");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-point.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-point.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,30 +19,20 @@
 #ifndef MALIKANIA_JS_POINT_HPP
 #define MALIKANIA_JS_POINT_HPP
 
-#include "js.hpp"
+#include "duktape.hpp"
 #include "point.hpp"
 
 namespace malikania {
 
-namespace duk {
+Point dukx_require_point(duk_context *ctx, duk_idx_t index);
 
-template <>
-class TypeTraits<Point> {
-public:
-    static Point get(ContextPtr ctx, Index index);
-
-    static Point require(ContextPtr ctx, Index index);
+Point dukx_get_point(duk_context *ctx, duk_idx_t index);
 
-    static Point optional(ContextPtr ctx, Index index, Point def);
-
-    static void push(ContextPtr ctx, const Point &point);
+void dukx_push_point(duk_context *ctx, const Point &point);
 
-    static void put(ContextPtr ctx, const Point &point);
-};
+void dukx_put_point(duk_context *ctx, const Point &point);
 
-} // !duk
-
-void loadMalikaniaPoint(duk::ContextPtr ctx);
+void dukx_load_point(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/js-rectangle.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-rectangle.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,79 +16,81 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cassert>
+
 #include "js-rectangle.hpp"
 
 namespace malikania {
 
 namespace {
 
-unsigned clamp(duk::ContextPtr ctx, int value, bool required)
+unsigned clamp(duk_context *ctx, int value, bool required)
 {
     if (value < 0) {
-        if (required) {
-            duk::raise(ctx, DUK_ERR_RANGE_ERROR, "%d can not be negative", value);
-        } else {
+        if (required)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d can not be negative", value);
+        else
             value = 0;
-        }
     }
 
     return static_cast<unsigned>(value);
 }
 
-Rectangle parse(duk::ContextPtr ctx, duk::Index index, bool required, Rectangle rect = {})
+Rectangle parse(duk_context *ctx, duk_idx_t index, bool required, Rectangle rect = {})
 {
-    duk::StackAssert sa(ctx);
+    StackAssert sa(ctx);
+
+    if (duk_is_object(ctx, index)) {
+        auto get = [&] (auto prop) {
+            if (required && !duk_has_prop_string(ctx, index, prop))
+                duk_error(ctx, DUK_ERR_ERROR, "missing '%s' property", prop);
+
+            duk_get_prop_string(ctx, index, prop);
 
-    if (duk::type(ctx, index) == DUK_TYPE_OBJECT) {
-        if (required && !duk::hasProperty(ctx, index, "x")) {
-            duk::raise(ctx, DUK_ERR_ERROR, "missing x property in rectangle description");
-        } else if (required && !duk::hasProperty(ctx, index, "y")) {
-            duk::raise(ctx, DUK_ERR_ERROR, "missing y property in rectangle description");
-        } else if (required && !duk::hasProperty(ctx, index, "width")) {
-            duk::raise(ctx, DUK_ERR_ERROR, "missing width property in rectangle description");
-        } else if (required && !duk::hasProperty(ctx, index, "height")) {
-            duk::raise(ctx, DUK_ERR_ERROR, "missing height property in rectangle description");
-        }
+            if (required && !duk_is_number(ctx, -1)) {
+                duk_pop(ctx);
+                duk_error(ctx, DUK_ERR_ERROR, "invalid '%s' property (number expected)", prop);
+            }
+
+            auto value = duk_to_int(ctx, -1);
 
-        rect = Rectangle(
-            duk::getProperty<int>(ctx, index, "x"),
-            duk::getProperty<int>(ctx, index, "y"),
-            clamp(ctx, duk::getProperty<int>(ctx, index, "width"), required),
-            clamp(ctx, duk::getProperty<int>(ctx, index, "height"), required)
-        );
-    } else if (required) {
-        duk::raise(ctx, DUK_ERR_TYPE_ERROR, "size object expected");
-    }
+            duk_pop(ctx);
+
+            return value;
+        };
+
+        rect = Rectangle(get("x"), get("y"),
+            clamp(ctx, get("width"), required), clamp(ctx, get("height"), required));
+    } else if (required)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "rectangle object expected");
 
     return rect;
 }
 
-duk::Ret constructor(duk::ContextPtr ctx)
+duk_ret_t constructor(duk_context *ctx)
 {
     Rectangle rect;
 
-    if (duk::top(ctx) == 4) {
+    if (duk_get_top(ctx) == 4) {
         rect = Rectangle(
-            duk::require<int>(ctx, 0),
-            duk::require<int>(ctx, 1),
-            clamp(ctx, duk::require<int>(ctx, 2), true),
-            clamp(ctx, duk::require<int>(ctx, 3), true)
+            duk_require_int(ctx, 0),
+            duk_require_int(ctx, 1),
+            clamp(ctx, duk_require_int(ctx, 2), true),
+            clamp(ctx, duk_require_int(ctx, 3), true)
         );
-    } else if (duk::top(ctx) == 1) {
+    } else if (duk_get_top(ctx) == 1)
         rect = parse(ctx, 0, true);
-    }
 
-    duk::Ret ret;
+    duk_ret_t ret;
 
-    /* Allow both constructor and non constructor calls */
+    // Allow both constructor and non constructor calls.
     if (duk_is_constructor_call(ctx)) {
-        duk::push(ctx, duk::This());
-        /* TODO: use duk::put when available */
-        duk::TypeTraits<Rectangle>::put(ctx, rect);
-        duk::pop(ctx);
+        duk_push_this(ctx);
+        dukx_put_rect(ctx, rect);
+        duk_pop(ctx);
         ret = 0;
     } else {
-        duk::push(ctx, rect);
+        dukx_push_rect(ctx, rect);
         ret = 1;
     }
 
@@ -97,52 +99,53 @@
 
 } // !namespace
 
-namespace duk {
-
-Rectangle TypeTraits<Rectangle>::get(ContextPtr ctx, Index index)
+Rectangle dukx_get_rect(duk_context *ctx, duk_idx_t index)
 {
     return parse(ctx, index, false);
 }
 
-Rectangle TypeTraits<Rectangle>::require(ContextPtr ctx, Index index)
+Rectangle dukx_require_rect(duk_context *ctx, duk_idx_t index)
 {
     return parse(ctx, index, true);
 }
 
-Rectangle TypeTraits<Rectangle>::optional(ContextPtr ctx, Index index, Rectangle def)
+Rectangle dukx_optional_rect(duk_context *ctx, duk_idx_t index, Rectangle def)
 {
     return parse(ctx, index, false, std::move(def));
 }
 
-void TypeTraits<Rectangle>::push(ContextPtr ctx, const Rectangle &rect)
+void dukx_push_rect(duk_context *ctx, const Rectangle &rect)
 {
-    duk::StackAssert sa(ctx, 1);
+    StackAssert sa(ctx, 1);
 
-    duk::push(ctx, duk::Object());
-    duk::TypeTraits<Rectangle>::put(ctx, rect);
+    duk_push_object(ctx);
+    dukx_put_rect(ctx, rect);
 }
 
-void TypeTraits<Rectangle>::put(ContextPtr ctx, const Rectangle &rect)
+void dukx_put_rect(duk_context *ctx, const Rectangle &rect)
 {
-    assert(duk::type(ctx, -1) == DUK_TYPE_OBJECT);
+    assert(duk_is_object(ctx, -1));
+
+    StackAssert sa(ctx);
 
-    duk::StackAssert sa(ctx);
-
-    duk::putProperty(ctx, -1, "x", rect.x());
-    duk::putProperty(ctx, -1, "y", rect.y());
-    duk::putProperty(ctx, -1, "width", static_cast<int>(rect.width()));
-    duk::putProperty(ctx, -1, "height", static_cast<int>(rect.height()));
+    duk_push_int(ctx, rect.x());
+    duk_put_prop_string(ctx, -2, "x");
+    duk_push_int(ctx, rect.y());
+    duk_put_prop_string(ctx, -2, "y");
+    duk_push_uint(ctx, rect.width());
+    duk_put_prop_string(ctx, -2, "width");
+    duk_push_uint(ctx, rect.height());
+    duk_put_prop_string(ctx, -2, "height");
 }
 
-} // !dukl
-
-void loadMalikaniaRectangle(duk::ContextPtr ctx)
+void dukx_load_rect(duk_context *ctx)
 {
-    duk::StackAssert sa(ctx, 0);
+    StackAssert sa(ctx, 0);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::putProperty(ctx, -1, "Rectangle", duk::Function{constructor, DUK_VARARGS});
-    duk::pop(ctx);
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Rectangle");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-rectangle.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-rectangle.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,14 +19,8 @@
 #ifndef MALIKANIA_JS_RECTANGLE_HPP
 #define MALIKANIA_JS_RECTANGLE_HPP
 
-#include "js.hpp"
-#include "rectangle.hpp"
-
-namespace malikania {
-
-namespace duk {
-
 /**
+ * \file js-rectangle.hpp
  * \brief JavaScript binding for Rectangle.
  *
  * Rectangles are plain objects.
@@ -40,62 +34,61 @@
  * }
  * ````
  */
-template <>
-class TypeTraits<Rectangle> {
-public:
-    /**
-     * Get a rectangle.
-     *
-     * The rectangle may be adjusted if any values are incorrect.
-     *
-     * \param ctx the context
-     * \param index the value index
-     * \return the rectangle
-     */
-    static Rectangle get(ContextPtr ctx, Index index);
+
+#include "duktape.hpp"
+#include "rectangle.hpp"
+
+namespace malikania {
 
-    /**
-     * Require a rectangle.
-     *
-     * If the object is not a rectangle or if width, height are invalid, raise a JavaScript error.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the rectangle
-     */
-    static Rectangle require(ContextPtr ctx, Index index);
+/**
+ * Get a rectangle.
+ *
+ * The rectangle may be adjusted if any values are incorrect.
+ *
+ * @param ctx the context
+ * @param index the value index
+ * @return the rectangle
+ */
+Rectangle dukx_get_rect(duk_context *ctx, duk_idx_t index);
 
+/**
+ * Require a rectangle.
+ *
+ * If the object is not a rectangle or if width, height are invalid, raise a JavaScript error.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @return the rectangle
+ */
+Rectangle dukx_require_rect(duk_context *ctx, duk_idx_t index);
 
-    /**
-     * Like get but return the default value if the value at the given index is not an object or invalid
-     *
-     * \param ctx the context
-     * \param index the idnex
-     * \param def the default value
-     * \return the rectangle
-     */
-    static Rectangle optional(ContextPtr ctx, Index index, Rectangle def);
+/**
+ * Like get but return the default value if the value at the given index is not an object or invalid
+ *
+ * @param ctx the context
+ * @param index the idnex
+ * @param def the default value
+ * @return the rectangle
+ */
+Rectangle dukx_optional_rect(duk_context *ctx, duk_idx_t index, Rectangle def);
 
-    /**
-     * Push the rectangle as object.
-     *
-     * \param ctx the context
-     * \param rect the rectangle
-     */
-    static void push(ContextPtr ctx, const Rectangle &rect);
+/**
+ * Push the rectangle as object.
+ *
+ * @param ctx the context
+ * @param rect the rectangle
+ */
+void dukx_push_rect(duk_context *ctx, const Rectangle &rect);
 
-    /**
-     * Put the rectangle properties into the object at the top of the stack.
-     *
-     * \param ctx the context
-     * \param rect the rectangle
-     */
-    static void put(ContextPtr ctx, const Rectangle &rect);
-};
+/**
+ * Put the rectangle properties into the object at the top of the stack.
+ *
+ * @param ctx the context
+ * @param rect the rectangle
+ */
+void dukx_put_rect(duk_context *ctx, const Rectangle &rect);
 
-} // !duk
-
-void loadMalikaniaRectangle(duk::ContextPtr ctx);
+void dukx_load_rect(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/js-size.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-size.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,67 +16,73 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cassert>
+
 #include "js-size.hpp"
 
 namespace malikania {
 
 namespace {
 
-unsigned clamp(duk::ContextPtr ctx, int value, bool required)
-{
-    if (value < 0) {
-        if (required)
-            duk::raise(ctx, DUK_ERR_RANGE_ERROR, "%d can not be negative", value);
-        else
-            value = 0;
-    }
-
-    return static_cast<unsigned>(value);
-}
-
-Size parse(duk::ContextPtr ctx, duk::Index index, bool required, Size size = {})
+Size parse(duk_context *ctx, duk_idx_t index, bool required, Size size = {})
 {
-    duk::StackAssert sa(ctx);
+    StackAssert sa(ctx);
+
+    if (duk_is_object(ctx, index)) {
+        if (required && !duk_has_prop_string(ctx, index, "width"))
+            duk_error(ctx, DUK_ERR_ERROR, "missing width property in size description");
+        else if (required && !duk_has_prop_string(ctx, index, "height"))
+            duk_error(ctx, DUK_ERR_ERROR, "missing height property in size description");
+
+        int width;
+        int height;
 
-    if (duk::type(ctx, index) == DUK_TYPE_OBJECT) {
-        if (required && !duk::hasProperty(ctx, index, "width"))
-            duk::raise(ctx, DUK_ERR_ERROR, "missing width property in size description");
-        else if (required && !duk::hasProperty(ctx, index, "height"))
-            duk::raise(ctx, DUK_ERR_ERROR, "missing height property in size description");
+        duk_get_prop_string(ctx, index, "width");
+        width = duk_to_int(ctx, -1);
+        duk_pop(ctx);
+        duk_get_prop_string(ctx, index, "height");
+        height = duk_to_int(ctx, -1);
+        duk_pop(ctx);
 
-        size = Size(
-            clamp(ctx, duk::getProperty<int>(ctx, index, "width"), required),
-            clamp(ctx, duk::getProperty<int>(ctx, index, "height"), required)
-        );
+        if (width < 0)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "width can not be negative");
+        if (height < 0)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "height can not be negative");
+
+        size = Size(width, height);
     } else if (required)
-        duk::raise(ctx, DUK_ERR_TYPE_ERROR, "size object expected");
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "size object expected");
 
     return size;
 }
 
-duk::Ret constructor(duk::ContextPtr ctx)
+duk_ret_t constructor(duk_context *ctx)
 {
-    malikania::Size size;
+    Size size;
+
+    if (duk_get_top(ctx) == 2) {
+        int width;
+        int height;
 
-    if (duk::top(ctx) == 2) {
-        size = malikania::Size(
-            clamp(ctx, duk::require<int>(ctx, 0), true),
-            clamp(ctx, duk::require<int>(ctx, 1), true)
-        );
-    } else if (duk::top(ctx) == 1)
+        if ((width = duk_require_int(ctx, 0)) < 0)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #0 can not be negative");
+        if ((height = duk_require_int(ctx, 1)) < 0)
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #1 can not be negative");
+
+        size = Size(static_cast<unsigned>(width), static_cast<unsigned>(height));
+    } else if (duk_get_top(ctx) == 1)
         size = parse(ctx, 0, true);
 
-    duk::Ret ret;
+    duk_ret_t ret;
 
     // Allow both constructor and non constructor calls.
     if (duk_is_constructor_call(ctx)) {
-        duk::push(ctx, duk::This());
-        /* TODO: use duk::put when available */
-        duk::TypeTraits<malikania::Size>::put(ctx, size);
-        duk::pop(ctx);
+        duk_push_this(ctx);
+        dukx_put_size(ctx, size);
+        duk_pop(ctx);
         ret = 0;
     } else {
-        duk::push(ctx, size);
+        dukx_push_size(ctx, size);
         ret = 1;
     }
 
@@ -85,50 +91,49 @@
 
 } // !namespace
 
-namespace duk {
-
-malikania::Size TypeTraits<malikania::Size>::get(ContextPtr ctx, Index index)
+Size dukx_get_size(duk_context *ctx, duk_idx_t index)
 {
     return parse(ctx, index, false);
 }
 
-malikania::Size TypeTraits<malikania::Size>::require(ContextPtr ctx, Index index)
+Size dukx_require_size(duk_context *ctx, duk_idx_t index)
 {
     return parse(ctx, index, true);
 }
 
-malikania::Size TypeTraits<malikania::Size>::optional(ContextPtr ctx, Index index, malikania::Size def)
+Size dukx_optional_size(duk_context *ctx, duk_idx_t index, Size def)
 {
     return parse(ctx, index, false, std::move(def));
 }
 
-void TypeTraits<malikania::Size>::push(ContextPtr ctx, const malikania::Size &size)
+void dukx_push_size(duk_context *ctx, const Size &size)
 {
     StackAssert sa(ctx, 1);
 
-    duk::push(ctx, duk::Object());
-    duk::TypeTraits<malikania::Size>::put(ctx, size);
+    duk_push_object(ctx);
+    dukx_put_size(ctx, size);
 }
 
-void TypeTraits<malikania::Size>::put(ContextPtr ctx, const malikania::Size &size)
+void dukx_put_size(duk_context *ctx, const Size &size)
 {
-    assert(type(ctx, -1) == DUK_TYPE_OBJECT);
+    assert(duk_is_object(ctx, -1));
 
     StackAssert sa(ctx, 0);
 
-    duk::putProperty(ctx, -1, "width", static_cast<int>(size.width()));
-    duk::putProperty(ctx, -1, "height", static_cast<int>(size.height()));
+    duk_push_uint(ctx, size.width());
+    duk_put_prop_string(ctx, -2, "width");
+    duk_push_uint(ctx, size.height());
+    duk_put_prop_string(ctx, -2, "height");
 }
 
-} // !duk
-
-void loadMalikaniaSize(duk::ContextPtr ctx)
+void dukx_load_size(duk_context *ctx)
 {
-    duk::StackAssert sa(ctx, 0);
+    StackAssert sa(ctx, 0);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::putProperty(ctx, -1, "Size", duk::Function{constructor, DUK_VARARGS});
-    duk::pop(ctx);
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, DUK_VARARGS);
+    duk_put_prop_string(ctx, -2, "Size");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-size.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-size.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,14 +19,8 @@
 #ifndef MALIKANIA_JS_SIZE_HPP
 #define MALIKANIA_JS_SIZE_HPP
 
-#include "js.hpp"
-#include "size.hpp"
-
-namespace malikania {
-
-namespace duk {
-
 /**
+ * \file js-size.h
  * \brief JavaScript binding for Size.
  *
  * Size are plain objects.
@@ -38,61 +32,61 @@
  * }
  * ````
  */
-template <>
-class TypeTraits<malikania::Size> {
-public:
-    /**
-     * Get a size.
-     *
-     * The size may be adjusted if any values are incorrect.
-     *
-     * \param ctx the context
-     * \param index the value index
-     * \return the size
-     */
-    static malikania::Size get(ContextPtr ctx, Index index);
+
+#include "duktape.hpp"
+#include "size.hpp"
+
+namespace malikania {
 
-    /**
-     * Require a size
-     *
-     * If the object is not a size, raise a JavaScript error.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the size
-     */
-    static malikania::Size require(ContextPtr ctx, Index index);
+/**
+ * Get a size.
+ *
+ * The size may be adjusted if any values are incorrect.
+ *
+ * @param ctx the context
+ * @param index the value index
+ * @return the size
+ */
+Size dukx_get_size(duk_context *ctx, duk_idx_t index);
+
+/**
+ * Require a size
+ *
+ * If the object is not a size, raise a JavaScript error.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @return the size
+ */
+Size dukx_require_size(duk_context *ctx, duk_idx_t index);
 
-    /**
-     * Like get but return the default value if the value at the given index is not an object.
-     *
-     * \param ctx the context
-     * \param index the idnex
-     * \param def the default value
-     * \return the size
-     */
-    static malikania::Size optional(ContextPtr ctx, Index index, malikania::Size def);
+/**
+ * Like get but return the default value if the value at the given index is not an object.
+ *
+ * @param ctx the context
+ * @param index the idnex
+ * @param def the default value
+ * @return the size
+ */
+Size dukx_optional_size(duk_context *ctx, duk_idx_t index, Size def);
 
-    /**
-     * Push the size as object.
-     *
-     * \param ctx the context
-     * \param size the size
-     */
-    static void push(ContextPtr ctx, const malikania::Size &size);
+/**
+ * Push the size as object.
+ *
+ * @param ctx the context
+ * @param size the size
+ */
+void dukx_push_size(duk_context *ctx, const Size &size);
 
-    /**
-     * Put the size properties into the object at the top of the stack.
-     *
-     * \param ctx the context
-     * \param size the size
-     */
-    static void put(ContextPtr ctx, const malikania::Size &size);
-};
+/**
+ * Put the size properties into the object at the top of the stack.
+ *
+ * @param ctx the context
+ * @param size the size
+ */
+void dukx_put_size(duk_context *ctx, const Size &size);
 
-} // !duk
-
-void loadMalikaniaSize(duk::ContextPtr ctx);
+void dukx_load_size(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/js-sprite.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-sprite.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,7 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "client-resources-loader.hpp"
+#include "js-client-resources-loader.hpp"
 #include "js-point.hpp"
 #include "js-size.hpp"
 #include "js-sprite.hpp"
@@ -26,122 +26,141 @@
 
 namespace {
 
-duk::Ret cell(duk::ContextPtr ctx)
+const std::string Signature("\xff""\xff""malikania-sprite-ptr");
+
+Sprite *self(duk_context *ctx)
 {
-    duk::push(ctx, duk::self<std::shared_ptr<Sprite>>(ctx)->cell());
+    StackAssert sa(ctx);
 
-    return 1;
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Sprite object");
+
+    return static_cast<Sprite *>(ptr);
 }
 
-duk::Ret columns(duk::ContextPtr ctx)
+duk_ret_t cell(duk_context *ctx)
 {
-    duk::push(ctx, static_cast<int>(duk::self<std::shared_ptr<Sprite>>(ctx)->columns()));
+    dukx_push_size(ctx, self(ctx)->cell());
 
     return 1;
 }
 
-duk::Ret margins(duk::ContextPtr ctx)
+duk_ret_t columns(duk_context *ctx)
 {
-    duk::push(ctx, duk::self<std::shared_ptr<Sprite>>(ctx)->margin());
+    duk_push_uint(ctx, self(ctx)->columns());
 
     return 1;
 }
 
-duk::Ret rows(duk::ContextPtr ctx)
+duk_ret_t margins(duk_context *ctx)
 {
-    duk::push(ctx, static_cast<int>(duk::self<std::shared_ptr<Sprite>>(ctx)->rows()));
+    dukx_push_size(ctx, self(ctx)->margin());
 
     return 1;
 }
 
-duk::Ret space(duk::ContextPtr ctx)
+duk_ret_t rows(duk_context *ctx)
 {
-    duk::push(ctx, duk::self<std::shared_ptr<Sprite>>(ctx)->space());
+    duk_push_uint(ctx, self(ctx)->rows());
 
     return 1;
 }
 
-duk::Ret constructor(duk::ContextPtr ctx)
+duk_ret_t space(duk_context *ctx)
+{
+    dukx_push_size(ctx, self(ctx)->space());
+
+    return 1;
+}
+
+duk_ret_t constructor(duk_context *ctx)
 {
     if (!duk_is_constructor_call(ctx))
-        duk::raise(ctx, DUK_ERR_ERROR, "sprite must be new-constructed");
+        duk_error(ctx, DUK_ERR_ERROR, "sprite must be new-constructed");
 
     try {
-        auto loader = duk::getGlobal<ClientResourcesLoader *>(ctx, "\xff""\xff""loader");
-        auto sprite = loader->loadSprite(duk::require<std::string>(ctx, 0));
+        auto loader = dukx_get_client_loader(ctx);
+        auto sprite = loader->loadSprite(duk_require_string(ctx, 0));
 
-        duk::construct(ctx, std::make_shared<Sprite>(std::move(sprite)));
-        duk::push(ctx, duk::This());
+        duk_push_this(ctx);
+        duk_push_pointer(ctx, new Sprite(std::move(sprite)));
+        duk_put_prop_string(ctx, -2, Signature.c_str());
 
         // Cell.
-        duk::push(ctx, "cell");
-        duk::push(ctx, duk::Function{cell});
-        duk::defineProperty(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+        duk_push_string(ctx, "cell");
+        duk_push_c_function(ctx, cell, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
 
         // Columns.
-        duk::push(ctx, "columns");
-        duk::push(ctx, duk::Function{columns});
-        duk::defineProperty(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+        duk_push_string(ctx, "columns");
+        duk_push_c_function(ctx, columns, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
 
         // Margins.
-        duk::push(ctx, "margins");
-        duk::push(ctx, duk::Function{margins});
-        duk::defineProperty(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+        duk_push_string(ctx, "margins");
+        duk_push_c_function(ctx, margins, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
 
         // Rows.
-        duk::push(ctx, "rows");
-        duk::push(ctx, duk::Function{rows});
-        duk::defineProperty(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+        duk_push_string(ctx, "rows");
+        duk_push_c_function(ctx, rows, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
 
         // Space.
-        duk::push(ctx, "space");
-        duk::push(ctx, duk::Function{space});
-        duk::defineProperty(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+        duk_push_string(ctx, "space");
+        duk_push_c_function(ctx, space, 0);
+        duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
 
-        duk::pop(ctx);
+        duk_pop(ctx);
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret draw(duk::ContextPtr ctx)
+duk_ret_t draw(duk_context *ctx)
 {
     try {
-        auto self = duk::self<std::shared_ptr<Sprite>>(ctx);
-        auto window = duk::get<std::shared_ptr<Window>>(ctx, 0);
-        auto cell = duk::require<int>(ctx, 1);
-        auto point = duk::get<Point>(ctx, 2);
+        auto sprite = self(ctx);
+        auto window = dukx_require_window(ctx, 0);
+        auto cell = duk_require_uint(ctx, 1);
+        auto point = dukx_get_point(ctx, 2);
 
-        if (cell < 0 || cell >= static_cast<int>(self->rows() * self->columns()))
-            duk::raise(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range", cell);
+        if (cell >= (sprite->rows() * sprite->columns()))
+            duk_error(ctx, DUK_ERR_RANGE_ERROR, "%d is out of range", cell);
 
-        self->draw(*window, static_cast<unsigned>(cell), point);
+        sprite->draw(*window, cell, point);
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-const duk::FunctionMap methods{
-    { "draw",    { draw,    3 } }
+const duk_function_list_entry methods[] = {
+    { "draw",   draw,       3 },
+    { nullptr,  nullptr,    0 }
 };
 
 } // !namespace
 
-void loadMalikaniaSprite(duk::ContextPtr ctx)
+void dukx_load_sprite(duk_context *ctx)
 {
-    duk::StackAssert sa(ctx);
+    StackAssert sa(ctx);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::push(ctx, duk::Function{constructor, 1});
-    duk::push(ctx, duk::Object());
-    duk::put(ctx, methods);
-    duk::putProperty(ctx, -2, "prototype");
-    duk::putProperty(ctx, -2, "Sprite");
-    duk::pop(ctx);
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 1);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Sprite");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-sprite.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-sprite.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,59 +19,12 @@
 #ifndef MALIKANIA_JS_SPRITE_HPP
 #define MALIKANIA_JS_SPRITE_HPP
 
-#include "js.hpp"
+#include "duktape.hpp"
 #include "sprite.hpp"
 
 namespace malikania {
 
-namespace duk {
-
-/**
- * \brief JavaScript binding for Sprite.
- */
-template <>
-class TypeTraits<Sprite> {
-public:
-    /**
-     * Put the Sprite prototype to the top of the stack.
-     *
-     * \param ctx the context
-     */
-    static void prototype(ContextPtr ctx)
-    {
-        duk::StackAssert sa(ctx, 1);
-
-        duk::getGlobal<void>(ctx, "Malikania");
-        duk::getGlobal<void>(ctx, "Sprite");
-        duk::getProperty<void>(ctx, -1, "prototype");
-        duk::remove(ctx, -2);
-        duk::remove(ctx, -2);
-    }
-
-    /**
-     * Get the object signature.
-     *
-     * \return Sprite signature
-     */
-    static inline std::string name()
-    {
-        return "\xff""\xff""Sprite";
-    }
-
-    /**
-     * Get inheritance list.
-     *
-     * \return empty
-     */
-    static inline std::vector<std::string> inherits()
-    {
-        return {};
-    }
-};
-
-} // !duk
-
-void loadMalikaniaSprite(duk::ContextPtr ctx);
+void dukx_load_sprite(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/js-window.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-window.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cassert>
+
 #include "js-color.hpp"
 #include "js-font.hpp"
 #include "js-line.hpp"
@@ -27,203 +29,256 @@
 
 namespace {
 
-duk::Ret constructor(duk::ContextPtr ctx)
+const std::string Signature("\xff""\xff""malikania-window-ptr");
+const std::string Prototype("\xff""\xff""malikania-window-prototype");
+
+Window *self(duk_context *ctx)
 {
-    duk::StackAssert sa(ctx);
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Window object");
+
+    return static_cast<Window *>(ptr);
+}
+
+duk_ret_t constructor(duk_context *ctx)
+{
+    StackAssert sa(ctx);
 
     if (!duk_is_constructor_call(ctx))
-        duk::raise(ctx, DUK_ERR_ERROR, "window must be new-constructed");
+        duk_error(ctx, DUK_ERR_ERROR, "window must be new-constructed");
 
-    /* TODO: add parameters */
+    // TODO: add parameters.
     try {
-        duk::construct(ctx, std::make_shared<Window>());
+        auto win = new Window;
+
+        duk_push_this(ctx);
+        duk_push_pointer(ctx, win);
+        duk_put_prop_string(ctx, -2, Signature.c_str());
+        duk_pop(ctx);
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret clear(duk::ContextPtr ctx)
+duk_ret_t clear(duk_context *ctx)
 {
     try {
-        duk::self<std::shared_ptr<Window>>(ctx)->clear();
+        self(ctx)->clear();
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk::Ret present(duk::ContextPtr ctx)
-{
-    try {
-        duk::self<std::shared_ptr<Window>>(ctx)->present();
-    } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret drawingColor(duk::ContextPtr ctx)
+duk_ret_t present(duk_context *ctx)
 {
     try {
-        duk::push(ctx, duk::self<std::shared_ptr<Window>>(ctx)->drawingColor());
+        self(ctx)->present();
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 1;
-}
-
-duk::Ret drawLine(duk::ContextPtr ctx)
-{
-    try {
-        duk::self<std::shared_ptr<Window>>(ctx)->drawLine(duk::require<Line>(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret drawLines(duk::ContextPtr ctx)
+duk_ret_t drawingColor(duk_context *ctx)
 {
     try {
-        duk::self<std::shared_ptr<Window>>(ctx)->drawLines(duk::get<std::vector<Point>>(ctx, 0));
+        dukx_push_color(ctx, self(ctx)->drawingColor());
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 1;
+}
+
+duk_ret_t drawLine(duk_context *ctx)
+{
+    try {
+        self(ctx)->drawLine(dukx_require_line(ctx, 0));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret drawPoint(duk::ContextPtr ctx)
+duk_ret_t drawLines(duk_context *ctx)
 {
     try {
-        duk::self<std::shared_ptr<Window>>(ctx)->drawPoint(duk::require<Point>(ctx, 0));
+        self(ctx)->drawLines(dukx_get_array(ctx, 0, dukx_get_point));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret drawPoints(duk::ContextPtr ctx)
+duk_ret_t drawPoint(duk_context *ctx)
 {
     try {
-        duk::self<std::shared_ptr<Window>>(ctx)->drawPoints(duk::get<std::vector<Point>>(ctx, 0));
+        self(ctx)->drawPoint(dukx_require_point(ctx, 0));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t drawPoints(duk_context *ctx)
+{
+    try {
+        self(ctx)->drawPoints(dukx_get_array(ctx, 0, dukx_get_point));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret drawRectangle(duk::ContextPtr ctx)
+duk_ret_t drawRectangle(duk_context *ctx)
 {
     try {
-        duk::self<std::shared_ptr<Window>>(ctx)->drawRectangle(duk::require<Rectangle>(ctx, 0));
+        self(ctx)->drawRectangle(dukx_require_rect(ctx, 0));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret drawRectangles(duk::ContextPtr ctx)
+duk_ret_t drawRectangles(duk_context *ctx)
 {
     try {
-        duk::self<std::shared_ptr<Window>>(ctx)->drawRectangles(duk::get<std::vector<Rectangle>>(ctx, 0));
+        self(ctx)->drawRectangles(dukx_get_array(ctx, 0, dukx_get_rect));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret drawText(duk::ContextPtr ctx)
+duk_ret_t drawText(duk_context *ctx)
 {
     try {
-        auto self = duk::self<std::shared_ptr<Window>>(ctx);
-        auto text = duk::require<std::string>(ctx, 0);
-        auto font = duk::get<std::shared_ptr<Font>>(ctx, 1);
-        auto rect = duk::get<Rectangle>(ctx, 2);
+        auto win = self(ctx);
+        auto text = duk_require_string(ctx, 0);
+        auto font = dukx_require_font(ctx, 1);
+        auto rect = dukx_get_rect(ctx, 2);
 
         if (!rect.isNull())
-            self->drawText(text, *font, rect);
+            win->drawText(text, *font, rect);
         else
-            self->drawText(text, *font, Point(rect.x(), rect.y()));
+            win->drawText(text, *font, Point(rect.x(), rect.y()));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret fillRectangle(duk::ContextPtr ctx)
+duk_ret_t fillRectangle(duk_context *ctx)
 {
     try {
-        duk::self<std::shared_ptr<Window>>(ctx)->fillRectangle(duk::require<Rectangle>(ctx, 0));
+        self(ctx)->fillRectangle(dukx_require_rect(ctx, 0));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+    }
+
+    return 0;
+}
+
+duk_ret_t fillRectangles(duk_context *ctx)
+{
+    try {
+        self(ctx)->fillRectangles(dukx_get_array(ctx, 0, dukx_get_rect));
+    } catch (const std::exception &ex) {
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-duk::Ret fillRectangles(duk::ContextPtr ctx)
+duk_ret_t setDrawingColor(duk_context *ctx)
 {
     try {
-        duk::self<std::shared_ptr<Window>>(ctx)->fillRectangles(duk::get<std::vector<Rectangle>>(ctx, 0));
+        self(ctx)->setDrawingColor(dukx_require_color(ctx, 0));
     } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
-    }
-
-    return 0;
-}
-
-duk::Ret setDrawingColor(duk::ContextPtr ctx)
-{
-    try {
-        duk::self<std::shared_ptr<Window>>(ctx)->setDrawingColor(duk::require<Color>(ctx, 0));
-    } catch (const std::exception &ex) {
-        duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+        duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
     }
 
     return 0;
 }
 
-const duk::FunctionMap methods{
-    { "clear",              { clear,            0 } },
-    { "drawingColor",       { drawingColor,     0 } },
-    { "drawLine",           { drawLine,         1 } },
-    { "drawLines",          { drawLines,        1 } },
-    { "drawPoint",          { drawPoint,        1 } },
-    { "drawPoints",         { drawPoints,       1 } },
-    { "drawRectangle",      { drawRectangle,    1 } },
-    { "drawRectangles",     { drawRectangles,   1 } },
-    { "drawText",           { drawText,         3 } },
-    { "fillRectangle",      { fillRectangle,    1 } },
-    { "fillRectangles",     { fillRectangles,   1 } },
-    { "present",            { present,          0 } },
-    { "setDrawingColor",    { setDrawingColor,  1 } }
+const duk_function_list_entry methods[] = {
+    { "clear",              clear,              0 },
+    { "drawingColor",       drawingColor,       0 },
+    { "drawLine",           drawLine,           1 },
+    { "drawLines",          drawLines,          1 },
+    { "drawPoint",          drawPoint,          1 },
+    { "drawPoints",         drawPoints,         1 },
+    { "drawRectangle",      drawRectangle,      1 },
+    { "drawRectangles",     drawRectangles,     1 },
+    { "drawText",           drawText,           3 },
+    { "fillRectangle",      fillRectangle,      1 },
+    { "fillRectangles",     fillRectangles,     1 },
+    { "present",            present,            0 },
+    { "setDrawingColor",    setDrawingColor,    1 },
+    { nullptr,              nullptr,            0 }
 };
 
 } // !namespace
 
-void loadMalikaniaWindow(duk::ContextPtr ctx)
+void dukx_new_window(duk_context *ctx, Window *window)
 {
-    duk::StackAssert sa(ctx);
+    assert(ctx);
+    assert(window);
+
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, window);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+}
+
+Window *dukx_require_window(duk_context *ctx, duk_idx_t index)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::push(ctx, duk::Function{constructor});
-    duk::push(ctx, duk::Object());
-    duk::put(ctx, methods);
-    duk::putProperty(ctx, -2, "prototype");
-    duk::putProperty(ctx, -2, "Window");
-    duk::pop(ctx);
+    duk_get_prop_string(ctx, index, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Window object");
+
+    return static_cast<Window *>(ptr);
+}
+
+void dukx_load_window(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 0);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "Window");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libclient/malikania/js-window.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/js-window.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,39 +19,14 @@
 #ifndef MALIKANIA_JS_WINDOW_HPP
 #define MALIKANIA_JS_WINDOW_HPP
 
-#include "js.hpp"
+#include "duktape.hpp"
 #include "window.hpp"
 
 namespace malikania {
 
-namespace duk {
+Window *dukx_require_window(duk_context *ctx, duk_idx_t index);
 
-/**
- * \brief JavaScript binding for Window.
- */
-template <>
-class TypeTraits<Window> {
-public:
-    /**
-     * Put the Window prototype to the top of the stack.
-     *
-     * \param ctx the context
-     */
-    static void prototype(duk::ContextPtr ctx)
-    {
-        duk::StackAssert sa(ctx, 1);
-
-        duk::getGlobal<void>(ctx, "Malikania");
-        duk::getProperty<void>(ctx, -1, "Window");
-        duk::getProperty<void>(ctx, -1, "prototype");
-        duk::remove(ctx, -2);
-        duk::remove(ctx, -2);
-    }
-};
-
-} // !duk
-
-void loadMalikaniaWindow(duk::ContextPtr ctx);
+void dukx_load_window(duk_context *ctx);
 
 } // !malikania
 
--- a/libclient/malikania/sprite.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/sprite.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cassert>
+
 #include "sprite.hpp"
 
 namespace malikania {
--- a/libclient/malikania/sprite.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/sprite.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -25,7 +25,6 @@
  */
 
 #include "image.hpp"
-#include "js.hpp"
 
 namespace malikania {
 
@@ -36,7 +35,7 @@
  * \class Sprite
  * \brief A Sprite is an image divided into cells.
  */
-class Sprite : public duk::Bindable {
+class Sprite {
 private:
     Image m_image;
     Size m_cell;
--- a/libclient/malikania/window.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libclient/malikania/window.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -29,8 +29,6 @@
 #include <vector>
 #include <string>
 
-#include "js.hpp"
-
 namespace malikania {
 
 class Color;
@@ -42,7 +40,7 @@
 /**
  * \brief Main window class and drawing.
  */
-class Window : public duk::Bindable {
+class Window  {
 private:
     class Backend;
 
--- a/libcommon/CMakeLists.txt	Fri Jul 01 13:32:08 2016 +0200
+++ b/libcommon/CMakeLists.txt	Wed Aug 10 14:30:51 2016 +0200
@@ -19,12 +19,12 @@
 set(
     HEADERS
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/application.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/game.hpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/duktape.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/elapsed-timer.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/game.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/id.hpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-elapsed-timer.hpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-resources-loader.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-loader.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-locator.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/util.hpp
@@ -35,6 +35,7 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/application.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/elapsed-timer.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-elapsed-timer.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-resources-loader.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-loader.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-locator.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/malikania/util.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/duktape.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -0,0 +1,505 @@
+/*
+ * duktape.hpp -- Duktape extras
+ *
+ * Copyright (c) 2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef DUKTAPE_HPP
+#define DUKTAPE_HPP
+
+/**
+ * \file duktape.hpp
+ * \brief Bring some extras to Duktape C library.
+ * \author David Demelier <markand@malikania.fr>
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <duktape.h>
+
+/**
+ * \class StackAssert
+ * \brief Stack sanity checker.
+ *
+ * Instanciate this class where you need to manipulate the Duktape stack outside
+ * a Duktape/C function, its destructor will examinate if the stack size matches
+ * the user expected size.
+ *
+ * When compiled with NDEBUG, this class does nothing.
+ *
+ * To use it, just declare an lvalue at the beginning of your function.
+ */
+class StackAssert {
+#if !defined(NDEBUG)
+private:
+    duk_context *m_context;
+    unsigned m_expected;
+    unsigned m_begin;
+#endif
+
+public:
+    /**
+     * Create the stack checker.
+     *
+     * No-op if NDEBUG is set.
+     *
+     * \param ctx the context
+     * \param expected the size expected relative to the already existing values
+     */
+    inline StackAssert(duk_context *ctx, unsigned expected = 0) noexcept
+#if !defined(NDEBUG)
+        : m_context(ctx)
+        , m_expected(expected)
+        , m_begin(static_cast<unsigned>(duk_get_top(ctx)))
+#endif
+    {
+#if defined(NDEBUG)
+        (void)ctx;
+        (void)expected;
+#endif
+    }
+
+    /**
+     * Verify the expected size.
+     *
+     * No-op if NDEBUG is set.
+     */
+    inline ~StackAssert() noexcept
+    {
+#if !defined(NDEBUG)
+        if (static_cast<unsigned>(duk_get_top(m_context)) - m_begin != m_expected) {
+            std::fprintf(stderr, "Corrupt stack detection in StackAssert:\n");
+            std::fprintf(stderr, "  Size at start:            %u\n", m_begin);
+            std::fprintf(stderr, "  Size at end:              %d\n", duk_get_top(m_context));
+            std::fprintf(stderr, "  Expected (user):          %u\n", m_expected);
+            std::fprintf(stderr, "  Expected (adjusted):      %u\n", m_expected + m_begin);
+            std::fprintf(stderr, "  Number of stale values:   %u\n", duk_get_top(m_context) - m_begin - m_expected);
+            std::abort();
+        }
+#endif
+    }
+};
+
+/**
+ * \class Exception
+ * \brief Error description.
+ *
+ * This class fills the fields got in an Error object.
+ */
+class Exception : public std::exception {
+public:
+    std::string name;       //!< name of error
+    std::string message;    //!< error message
+    std::string stack;      //!< stack if available
+    std::string fileName;   //!< filename if applicable
+    int lineNumber{0};      //!< line number if applicable
+
+    /**
+     * Get the error message. This effectively returns message field.
+     *
+     * \return the message
+     */
+    const char *what() const noexcept override
+    {
+        return message.c_str();
+    }
+};
+
+/**
+ * \brief RAII based Duktape handler.
+ *
+ * This class is implicitly convertible to duk_context for convenience.
+ */
+class UniqueContext {
+private:
+    using Deleter = void (*)(duk_context *);
+    using Handle = std::unique_ptr<duk_context, Deleter>;
+
+    Handle m_handle;
+
+    UniqueContext(const UniqueContext &) = delete;
+    UniqueContext &operator=(const UniqueContext &) = delete;
+
+public:
+    /**
+     * Create default context.
+     */
+    inline UniqueContext()
+        : m_handle(duk_create_heap_default(), duk_destroy_heap)
+    {
+    }
+
+    /**
+     * Default move constructor.
+     */
+    UniqueContext(UniqueContext &&) noexcept = default;
+
+    /**
+     * Convert the context to the native Duktape/C type.
+     *
+     * \return the duk_context
+     */
+    inline operator duk_context *() noexcept
+    {
+        return m_handle.get();
+    }
+
+    /**
+     * Convert the context to the native Duktape/C type.
+     *
+     * \return the duk_context
+     */
+    inline operator duk_context *() const noexcept
+    {
+        return m_handle.get();
+    }
+
+    /**
+     * Default move assignment operator.
+     *
+     * \return this
+     */
+    UniqueContext &operator=(UniqueContext &&) noexcept = delete;
+};
+
+/**
+ * \class Error
+ * \brief Base ECMAScript error class.
+ * \warning Override the function create for your own exceptions
+ */
+class Error {
+private:
+    int m_type{DUK_ERR_ERROR};
+    std::string m_message;
+
+protected:
+    /**
+     * Constructor with a type of error specified, specially designed for
+     * derived errors.
+     *
+     * \param type of error (e.g. DUK_ERR_ERROR)
+     * \param message the message
+     */
+    inline Error(int type, std::string message) noexcept
+        : m_type(type)
+        , m_message(std::move(message))
+    {
+    }
+
+public:
+    /**
+     * Constructor with a message.
+     *
+     * \param message the message
+     */
+    inline Error(std::string message) noexcept
+        : m_message(std::move(message))
+    {
+    }
+
+    /**
+     * Create the exception on the stack.
+     *
+     * \note the default implementation search for the global variables
+     * \param ctx the context
+     */
+    virtual void raise(duk_context *ctx) const
+    {
+        duk_error(ctx, m_type, "%s", m_message.c_str());
+    }
+};
+
+/**
+ * \class EvalError
+ * \brief Error in eval() function.
+ */
+class EvalError : public Error {
+public:
+    /**
+     * Construct an EvalError.
+     *
+     * \param message the message
+     */
+    inline EvalError(std::string message) noexcept
+        : Error(DUK_ERR_EVAL_ERROR, std::move(message))
+    {
+    }
+};
+
+/**
+ * \class RangeError
+ * \brief Value is out of range.
+ */
+class RangeError : public Error {
+public:
+    /**
+     * Construct an RangeError.
+     *
+     * \param message the message
+     */
+    inline RangeError(std::string message) noexcept
+        : Error(DUK_ERR_RANGE_ERROR, std::move(message))
+    {
+    }
+};
+
+/**
+ * \class ReferenceError
+ * \brief Trying to use a variable that does not exist.
+ */
+class ReferenceError : public Error {
+public:
+    /**
+     * Construct an ReferenceError.
+     *
+     * \param message the message
+     */
+    inline ReferenceError(std::string message) noexcept
+        : Error(DUK_ERR_REFERENCE_ERROR, std::move(message))
+    {
+    }
+};
+
+/**
+ * \class SyntaxError
+ * \brief Syntax error in the script.
+ */
+class SyntaxError : public Error {
+public:
+    /**
+     * Construct an SyntaxError.
+     *
+     * \param message the message
+     */
+    inline SyntaxError(std::string message) noexcept
+        : Error(DUK_ERR_SYNTAX_ERROR, std::move(message))
+    {
+    }
+};
+
+/**
+ * \class TypeError
+ * \brief Invalid type given.
+ */
+class TypeError : public Error {
+public:
+    /**
+     * Construct an TypeError.
+     *
+     * \param message the message
+     */
+    inline TypeError(std::string message) noexcept
+        : Error(DUK_ERR_TYPE_ERROR, std::move(message))
+    {
+    }
+};
+
+/**
+ * \class URIError
+ * \brief URI manipulation failure.
+ */
+class URIError : public Error {
+public:
+    /**
+     * Construct an URIError.
+     *
+     * \param message the message
+     */
+    inline URIError(std::string message) noexcept
+        : Error(DUK_ERR_URI_ERROR, std::move(message))
+    {
+    }
+};
+
+/**
+ * Get the error object when a JavaScript error has been thrown (e.g. eval
+ * failure).
+ *
+ * \param ctx the context
+ * \param index the index
+ * \param pop if true, also remove the exception from the stack
+ * \return the information
+ */
+inline Exception dukx_exception(duk_context *ctx, int index, bool pop = true)
+{
+    Exception ex;
+
+    index = duk_normalize_index(ctx, index);
+
+    duk_get_prop_string(ctx, index, "name");
+    ex.name = duk_to_string(ctx, -1);
+    duk_get_prop_string(ctx, index, "message");
+    ex.message = duk_to_string(ctx, -1);
+    duk_get_prop_string(ctx, index, "fileName");
+    ex.fileName = duk_to_string(ctx, -1);
+    duk_get_prop_string(ctx, index, "lineNumber");
+    ex.lineNumber = duk_to_int(ctx, -1);
+    duk_get_prop_string(ctx, index, "stack");
+    ex.stack = duk_to_string(ctx, -1);
+    duk_pop_n(ctx, 5);
+
+    if (pop)
+        duk_remove(ctx, index);
+
+    return ex;
+}
+
+/**
+ * Throw an ECMAScript exception.
+ *
+ * \param ctx the context
+ * \param ex the exception
+ */
+template <typename Exception>
+void dukx_throw(duk_context *ctx, const Exception &ex)
+{
+    ex.raise(ctx);
+}
+
+/**
+ * Get a string, return 0 if not a string.
+ *
+ * \param ctx the context
+ * \param index the index
+ * \return the string
+ */
+inline std::string dukx_get_std_string(duk_context *ctx, int index)
+{
+    duk_size_t size;
+    const char *text = duk_get_lstring(ctx, index, &size);
+
+    return std::string(text, size);
+}
+
+/**
+ * Require a string, throws a JavaScript exception if not a string.
+ *
+ * \param ctx the context
+ * \param index the index
+ * \return the string
+ */
+inline std::string dukx_require_std_string(duk_context *ctx, int index)
+{
+    duk_size_t size;
+    const char *text = duk_require_lstring(ctx, index, &size);
+
+    return std::string(text, size);
+}
+
+/**
+ * Push a C++ string.
+ *
+ * \param ctx the context
+ * \param str the string
+ */
+inline void dukx_push_std_string(duk_context *ctx, const std::string &str)
+{
+    duk_push_lstring(ctx, str.data(), str.length());
+}
+
+/**
+ * Get an array.
+ *
+ * \param ctx the context
+ * \param index the array index
+ * \param get the conversion function (e.g. duk_get_int)
+ */
+template <typename Getter>
+auto dukx_get_array(duk_context *ctx, duk_idx_t index, Getter &&get)
+{
+    using T = decltype(get(ctx, 0));
+
+    std::vector<T> result;
+    std::size_t length = duk_get_length(ctx, index);
+
+    for (std::size_t i = 0; i < length; ++i) {
+        duk_get_prop_index(ctx, -1, i);
+        result.push_back(get(ctx, -1));
+        duk_pop(ctx);
+    }
+
+    return result;
+}
+
+/**
+ * Push an array.
+ *
+ * \param ctx the context
+ * \param values the values
+ * \param push the function to push values
+ */
+template <typename T, typename Pusher>
+void dukx_push_array(duk_context *ctx, const std::vector<T> &values, Pusher &&push)
+{
+    duk_push_array(ctx);
+
+    int i = 0;
+    for (auto x : values) {
+        push(ctx, x);
+        duk_put_prop_index(ctx, -2, i++);
+    }
+}
+
+/**
+ * Get an object.
+ *
+ * \param ctx the context
+ * \param index the object index
+ * \param get the conversion function (e.g. duk_get_int)
+ */
+template <typename Getter>
+auto dukx_get_object(duk_context *ctx, duk_idx_t index, Getter &&get)
+{
+    using T = decltype(get(ctx, 0));
+
+    std::unordered_map<std::string, T> result;
+
+    duk_enum(ctx, index, 0);
+
+    while (duk_next(ctx, -1, true)) {
+        result.emplace(dukx_get_std_string(ctx, -2), get(ctx, -1));
+        duk_pop_2(ctx);
+    }
+
+    duk_pop(ctx);
+
+    return result;
+}
+
+/**
+ * Push an object.
+ *
+ * \param ctx the context
+ * \param values the values
+ * \param push the function to push values
+ */
+template <typename T, typename Pusher>
+void dukx_push_object(duk_context *ctx, const std::unordered_map<std::string, T> &values, Pusher &&push)
+{
+    duk_push_object(ctx);
+
+    for (const auto &pair : values) {
+        push(ctx, pair.second);
+        duk_put_prop_string(ctx, -2, pair.first.c_str());
+    }
+}
+
+#endif // !DUKTAPE_HPP
--- a/libcommon/malikania/elapsed-timer.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libcommon/malikania/elapsed-timer.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -26,8 +26,6 @@
 
 #include <chrono>
 
-#include "js.hpp"
-
 namespace malikania {
 
 /**
@@ -40,7 +38,7 @@
  * It uses std::chrono::high_resolution_clock for more precision and uses
  * milliseconds only.
  */
-class ElapsedTimer : public duk::Bindable {
+class ElapsedTimer {
 public:
     using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
 
--- a/libcommon/malikania/js-elapsed-timer.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libcommon/malikania/js-elapsed-timer.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -16,22 +16,42 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cassert>
+#include <string>
+
 #include "elapsed-timer.hpp"
-#include "js.hpp"
+#include "duktape.hpp"
 
 namespace malikania {
 
 namespace {
 
+const std::string Signature("\xff" "\xff" "malikania-elapsed-timer-ptr");
+
+ElapsedTimer *self(duk_context *ctx)
+{
+    StackAssert sa(ctx);
+
+    duk_push_this(ctx);
+    duk_get_prop_string(ctx, -1, Signature.c_str());
+    auto ptr = duk_to_pointer(ctx, -1);
+    duk_pop_2(ctx);
+
+    if (!ptr)
+        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an ElapsedTimer object");
+
+    return static_cast<ElapsedTimer *>(ptr);
+}
+
 /*
  * Method: ElapsedTimer.pause
  * ------------------------------------------------------------------
  *
  * Pause the timer, without resetting the current elapsed time stored.
  */
-duk::Ret pause(duk::ContextPtr ctx)
+duk_ret_t pause(duk_context *ctx)
 {
-    duk::self<std::shared_ptr<ElapsedTimer>>(ctx)->pause();
+    self(ctx)->pause();
 
     return 0;
 }
@@ -42,9 +62,9 @@
  *
  * Reset the elapsed time to 0, the status is not modified.
  */
-duk::Ret reset(duk::ContextPtr ctx)
+duk_ret_t reset(duk_context *ctx)
 {
-    duk::self<std::shared_ptr<ElapsedTimer>>(ctx)->reset();
+    self(ctx)->reset();
 
     return 0;
 }
@@ -55,9 +75,9 @@
  *
  * Restart the timer without resetting the current elapsed time.
  */
-duk::Ret restart(duk::ContextPtr ctx)
+duk_ret_t restart(duk_context *ctx)
 {
-    duk::self<std::shared_ptr<ElapsedTimer>>(ctx)->restart();
+    self(ctx)->restart();
 
     return 0;
 }
@@ -71,9 +91,9 @@
  * Returns:
  *   The time elapsed.
  */
-duk::Ret elapsed(duk::ContextPtr ctx)
+duk_ret_t elapsed(duk_context *ctx)
 {
-    duk::push(ctx, static_cast<int>(duk::self<std::shared_ptr<ElapsedTimer>>(ctx)->elapsed()));
+    duk_push_uint(ctx, self(ctx)->elapsed());
 
     return 1;
 }
@@ -84,33 +104,55 @@
  *
  * Construct a new ElapsedTimer object.
  */
-duk::Ret constructor(duk::ContextPtr ctx)
+duk_ret_t constructor(duk_context *ctx)
 {
-    duk::construct(ctx, std::make_shared<ElapsedTimer>());
+    duk_push_this(ctx);
+    duk_push_pointer(ctx, new ElapsedTimer);
+    duk_put_prop_string(ctx, -2, Signature.c_str());
+    duk_pop(ctx);
+
+    return 0;
+}
+
+/*
+ * Function: Malikania.ElapsedTimer() [destructor]
+ * ------------------------------------------------------------------
+ *
+ * Destroy the timer.
+ */
+duk_ret_t destructor(duk_context *ctx)
+{
+    duk_get_prop_string(ctx, 0, Signature.c_str());
+    delete static_cast<ElapsedTimer *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+    duk_del_prop_string(ctx, 0, Signature.c_str());
 
     return 0;
 }
 
-const duk::FunctionMap methods{
-    { "elapsed",    { elapsed,  0 } },
-    { "pause",      { pause,    0 } },
-    { "reset",      { reset,    0 } },
-    { "restart",    { restart,  0 } }
+const duk_function_list_entry methods[] = {
+    { "elapsed",    elapsed,    0 },
+    { "pause",      pause,      0 },
+    { "reset",      reset,      0 },
+    { "restart",    restart,    0 },
+    { nullptr,      nullptr,    0 }
 };
 
 } // !namespace
 
-void loadJsElapsedTimer(duk::ContextPtr ctx) noexcept
+void dukx_load_elapsedtimer(duk_context *ctx) noexcept
 {
-    duk::StackAssert sa(ctx);
+    StackAssert sa(ctx);
 
-    duk::getGlobal<void>(ctx, "Malikania");
-    duk::push(ctx, duk::Function{constructor, 0});
-    duk::push(ctx, duk::Object{});
-    duk::put(ctx, methods);
-    duk::putProperty(ctx, -2, "prototype");
-    duk::putProperty(ctx, -2, "ElapsedTimer");
-    duk::pop(ctx);
+    duk_get_global_string(ctx, "Malikania");
+    duk_push_c_function(ctx, constructor, 0);
+    duk_push_object(ctx);
+    duk_put_function_list(ctx, -1, methods);
+    duk_push_c_function(ctx, destructor, 1);
+    duk_set_finalizer(ctx, -2);
+    duk_put_prop_string(ctx, -2, "prototype");
+    duk_put_prop_string(ctx, -2, "ElapsedTimer");
+    duk_pop(ctx);
 }
 
 } // !malikania
--- a/libcommon/malikania/js-elapsed-timer.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/libcommon/malikania/js-elapsed-timer.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -19,11 +19,11 @@
 #ifndef MALIKANIA_JS_ELAPSED_TIMER_HPP
 #define MALIKANIA_JS_ELAPSED_TIMER_HPP
 
-#include "js.hpp"
+#include "duktape.hpp"
 
 namespace malikania {
 
-void loadJsElapsedTimer(duk::ContextPtr ctx) noexcept;
+void dukx_load_elapsedtimer(duk_context *ctx) noexcept;
 
 } // !malikania
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/js-resources-loader.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -0,0 +1,55 @@
+/*
+ * js-resources-loader.cpp --resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cassert>
+
+#include "js-resources-loader.hpp"
+
+namespace malikania {
+
+namespace {
+
+const std::string Variable("\xff""\xff""malikania-resources-loader");
+
+} // !namespace
+
+void dukx_put_loader(duk_context *ctx, ResourcesLoader *loader)
+{
+    assert(ctx);
+    assert(loader);
+
+    StackAssert sa(ctx);
+
+    duk_push_pointer(ctx, loader);
+    duk_put_global_string(ctx, Variable.c_str());
+}
+
+ResourcesLoader *duk_require_loader(duk_context *ctx)
+{
+    assert(ctx);
+
+    StackAssert sa(ctx);
+
+    duk_get_global_string(ctx, Variable.c_str());
+    auto ptr = static_cast<ResourcesLoader *>(duk_to_pointer(ctx, -1));
+    duk_pop(ctx);
+
+    return static_cast<ResourcesLoader *>(ptr);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/js-resources-loader.hpp	Wed Aug 10 14:30:51 2016 +0200
@@ -0,0 +1,33 @@
+/*
+ * js-resources-loader.hpp --resources loader (JavaScript binding)
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_JS_RESOURCES_LOADER_H
+#define MALIKANIA_JS_RESOURCES_LOADER_H
+
+#include "duktape.hpp"
+#include "resources-loader.hpp"
+
+namespace malikania {
+
+void dukx_put_loader(duk_context *ctx, ResourcesLoader *);
+
+ResourcesLoader *dukx_get_loader(duk_context *ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_RESOURCES_LOADER_H
--- a/libcommon/malikania/js.hpp	Fri Jul 01 13:32:08 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3103 +0,0 @@
-/*
- * js.hpp -- JavaScript C++14 wrapper for Duktape
- *
- * Copyright (c) 2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_JS_HPP
-#define MALIKANIA_JS_HPP
-
-/**
- * \file js.hpp
- * \brief Bring JavaScript using Duktape.
- *
- * This file provides usual Duktape function renamed and placed into `duk` namespace. It also replaces error
- * code with exceptions when possible.
- *
- * For convenience, this file also provides templated functions, overloads and much more.
- */
-
-/**
- * \page js JavaScript binding
- * \brief JavaScript binding using Duktape
- *
- * This page will show you how to setup this module to host JavaScript environment into your C++ application.
- *
- * ## Duktape
- *
- * Duktape is a C library designed for performance, small footprint and conformance. This wrapper is built top of it and
- * requires it at build and runtime.
- *
- * It is highly recommended that you read the [Duktape guide](http://duktape.org/guide.html) before continuing because
- * a lot of concepts are kept as-is.
- *
- * ## Installation
- *
- * You need the Duktape source amalgamation, it is provided with this module.
- *
- * When compiling, be sure to enable `-DDUK_OPT_CPP_EXCEPTIONS` and that Duktape source file has **cpp** extension.
- *
- * Just copy the **js.hpp** file and include it into your project. The header depends on **duktape.h** so be sure to
- * provide it when compiling.
- *
- * @subpage js-init
- * @subpage js-types
- * @subpage js-basics
- * @subpage js-more
- * @subpage js-concepts
- */
-
-/**
- * \page js-init Initialization
- * \brief Context initialization.
- *
- * To host JavaScript, you need a context. Usually one is sufficient but you can create as many as you want but they
- * won't share any resource.
- *
- * @code
- * #include "js.hpp"
- *
- * int main()
- * {
- *   duk::Context ctx;
- *
- *   return 0;
- * }
- * @endcode
- *
- * The duk::Context class is a RAII based wrapper around the native duk_context structure. It is automatically created
- * and closed in the destructor.
- *
- * Be sure to not keep any pointer to it.
- */
-
-/**
- * \page js-types Predefined types
- * \brief Default duk::TypeTraits specializations
- *
- * The following specializations are provided with libjs.
- *
- * ## Primitive types
- *
- * | Type           | Support                          | Remarks                               |
- * |----------------|----------------------------------|---------------------------------------|
- * | `int`          | get, is, optional, push, require |                                       |
- * | `bool`         | get, is, optional, push, require |                                       |
- * | `double`       | get, is, optional, push, require |                                       |
- * | `std::string`  | get, is, optional, push, require | can contain '\0' and binary data      |
- * | `const char *` | get, is, optional, push, require |                                       |
- * | `unsigned`     | get, is, optional, push, require |                                       |
- * | T *            | get, is, optional, push, require | raw pointer, never deleted by Duktape |
- *
- * ## Special JavaScript types
- *
- * The following types are used to create or inspect JavaScript types.
- *
- * | Type             | Support  | Remarks                                |
- * |------------------|----------|----------------------------------------|
- * | duk::Array       | is, push |                                        |
- * | duk::Function    | is, push | is just check if the value is callable |
- * | duk::FunctionMap | put      |                                        |
- * | duk::Global      | push     |                                        |
- * | duk::Null        | is, push |                                        |
- * | duk::Object      | is, push |                                        |
- * | duk::This        | push     |                                        |
- * | duk::Undefined   | is, push |                                        |
- *
- * ## Partial specializations
- *
- * These partial specializations will use complete specialization for T.
- *
- * | Type                               | Support   | Remarks                |
- * |------------------------------------|-----------|------------------------|
- * | std::unordered_map<std::string, T> | push, put | push or put properties |
- * | std::vector<T>                     | push, put | push array of values   |
- *
- * ## Special types
- *
- * These types are used to export C++ object to JavaScript. See @ref js-more-t2 for more explanations and
- * @ref js-concept-class.
- *
- * | Type               | Support                                 | Remarks                        |
- * |--------------------|-----------------------------------------|--------------------------------|
- * | std::shared_ptr<T> | construct, get, optional, push, require | T must have Class requirements |
- */
-
-/**
- * \page js-basics Basics
- * \brief Basics use case.
- *
- * The following topics are sample use case of the C++ front end. It does not use extended features that this module
- * provides.
- *
- * @subpage js-basics-t1
- * @subpage js-basics-t2
- * @subpage js-basics-t3
- */
-
-/**
- * \page js-basics-t1 Example 1: call JavaScript code from C++
- * \brief Evaluate JavaScript code from C++.
- *
- * Let use JavaScript to compute a simple expression.
- *
- * @code
- * #include "js.hpp"
- *
- * int main()
- * {
- *   duk::Context ctx;
- *
- *   duk::pevalString(ctx, "1 + 1");
- *   std::cout << duk::get<int>(ctx -1) << std::endl;
- *
- *   return 0;
- * }
- * @endcode
- */
-
-/**
- * \page js-basics-t2 Example 2: call C++ code from JavaScript
- * \brief Evaluate a function from JavaScript.
- *
- * In that example, we will add a C++ function to JavaScript and call it from the script. The function just compute the
- * two arguments that are passed through the function and return the result.
- *
- * We take the benefits of C++11 to map the function. The lambda can not have a capture because Duktape use raw C
- * function pointers and this module keep them.
- *
- * @code
- * #include "js.hpp"
- *
- * int main()
- * {
- *   duk::Context ctx;
- *
- *   // Push a function as global "add"
- *   duk::putGlobal(ctx, "add", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
- *     int x = duk::require<int>(ctx, 0);
- *     int y = duk::require<int>(ctx, 1);
- *
- *     duk::push(ctx, x + y);
- *
- *     return 1;
- *   }, 2});
- *
- *   // Evaluate from JavaScript
- *   duk::pevalString(ctx, "add(1, 2)");
- *
- *   return 0;
- * }
- * @endcode
- *
- * Please note the **2** at end of lambda which indicates that the function takes 2 arguments. If number of arguments
- * is variadic, pass DUK_VARARGS there.
- */
-
-/**
- * \page js-basics-t3 Example 3: pushing and getting values
- * \brief Manage values between JavaScript and C++.
- *
- * As you have seen in the previous examples, we were pushing some values to the Duktape context.
- *
- * With the C Duktape frontend, you usually use duk_push_int, duk_push_string and all other related functions. The libjs
- * module provides an uniform and convenient way for sharing values with the same functions.
- *
- * See the description of duk::TypeTraits to see the supported types.
- *
- * ## Push
- *
- * The duk::push function is a template that accept most of the primitives types. It uses the specializations of the
- * duk::TypeTraits class (described later).
- *
- * Example of code
- *
- * @code
- * duk::push(ctx, 123); // an integer
- * duk::push(ctx, true); // a boolean
- * @endcode
- *
- * The push function add a new value to the stack for any specialization of TypeTraits provided by libjs.
- *
- * ## Get
- *
- * The duk::get function is similar to duk_get_ functions. It usually does not check the value and return a sane default
- * value.
- *
- * This template function does not take the template argument so it can't be deduced and must be specified explicitly.
- *
- * @code
- * duk::get<int>(ctx, 0) // get an int at index 0
- * duk::get<std::string>(ctx, 1) // get a std::string at index 1
- * @endcode
- *
- * ## Require
- *
- * The duk::require function is similar to duk_require functions. It requires the exact type at the given index. If the
- * value is invalid a JavaScript error is propagated.
- *
- * @code
- * duk::require<int>(ctx, 0) // require an int at index 0 or raise an error
- * @endcode
- *
- * ## Put
- *
- * This special function is similar to push except that it applies to the existing object at the top of the stack. It
- * is usually implemented for map and vector.
- *
- * @code
- * // Fill the object at the top of the stack with this map
- * std:unordered_map<std::string, int> map{
- *   { "value1", 1 },
- *   { "value2", 2 }
- * };
- *
- * duk::put(ctx, map);
- * @endcode
- *
- * ## Is
- *
- * This function duk::is checks if the value at the given index is of the given type and return true.
- *
- * Just like duk::get, this function need the explicit template parameter.
- *
- * @code
- * duk::push(ctx, 1);
- * duk::is<int>(ctx, -1); // true
- * @endcode
- *
- * ## Optional
- *
- * The duk::optional function has no equivalent in Duktape C API. It is a convenient way to get values with a default
- * replacement is not available.
- *
- * The common implementation uses duk::is and then duk::get.
- *
- * @code
- * duk::optional<int>(ctx, -1, 123); // 123 is -1 has no value or is not an int
- * @endcode
- */
-
-/**
- * \page js-more Extensions and advanced features.
- * \brief Evolved extensions provided by libjs.
- *
- * The following topics are provided by libjs and have no equivalent in Duktape C API.
- *
- * @subpage js-more-t1
- * @subpage js-more-t2
- */
-
-/**
- * \page js-more-t1 Advanced 1: adding your own types to TypeTraits
- * \brief How to specialize duk::TypeTraits structure.
- *
- * This topic shows how you can specialize the duk::TypeTraits structure to add more types.
- *
- * Specializing the duk::TypeTraits is usually only needed when you want to convert a C++ object into JavaScript, for
- * exporting a C++ class, see @ref js-more-t2.
- *
- * In this example we will convert a C++ small structure containing two integers to JavaScript.
- *
- * \note It is not required to implement all functions from duk::TypeTraits. Just provide which one you need.
- *
- * ## The C++ structure
- *
- * The point does not have any methods, it just a description of two integers.
- *
- * @code
- * struct Point {
- *   int x;
- *   int y;
- * };
- * @endcode
- *
- * ## The push function
- *
- * Let's add a push function that will create a JavaScript object with **x** and **y** properties.
- *
- * @code
- * namespace duk {
- *
- * template <>
- * class TypeTraits<Point> {
- * public:
- *   static void push(ContextPtr ctx, const Point &point)
- *   {
- *     // Create an object
- *     push(ctx, Object());
- *
- *     // Set x
- *     putProperty(ctx, -1, "x", point.x);
- *
- *     // Set y
- *     putProperty(ctx, -1, "y", point.y);
- *   }
- * };
- *
- * }
- * @endcode
- *
- * You can safely use different type of reference as second argument.
- *
- * That's it, you can now safely invoke `duk::push(ctx, Point{100, 200});`.
- *
- * ## The get function
- *
- * The get function usually return a new object. The recommandation is to provide sane defaults except if you have any
- * reason to not do so.
- *
- * @code
- * namespace duk {
- *
- * template <>
- * class TypeTraits<Point> {
- * public:
- *   static Point get(ContextPtr ctx, Index index)
- *   {
- *     Point point{0, 0};
- *
- *     if (is<Object>(ctx, index)) {
- *       point.x = getProperty<int>(ctx, index, "x");
- *       point.y = getProperty<int>(ctx, index, "y");
- *     }
- *
- *     return point;
- *   }
- * };
- *
- * }
- * @endcode
- *
- * Now you can invoke `duk::get<Point>(ctx, 0)` to convert a JavaScript object to the Point structure.
- *
- * ## The require function
- *
- * The require function has the same signature as get. It's up to you to decide which criterias makes the object not
- * suitable for conversion.
- *
- * In that example, we will require that object at the index is a JavaScript object and that **x**, **y** are present.
- *
- * @code
- * namespace duk {
- *
- * template <>
- * class TypeTraits<Point> {
- * public:
- *   static Point require(ContextPtr ctx, Index index)
- *   {
- *     Point point;
- *
- *     // Raise an error if not object
- *     if (!is<Object>(ctx, index))
- *       duk::raise(ctx, TypeError("object required"));
- *
- *     // Get x, for simplicity we just check that x and y exist.
- *     if (!hasProperty(ctx, index, "x"))
- *       duk::raise(ctx, TypeError("property x missing"));
- *
- *     // Get y
- *     if (!hasProperty(ctx, index, "y"))
- *       duk::raise(ctx, TypeError("property y missing"));
- *
- *     // Note: if you need more security, check that types are integers too.
- *     point.x = duk::getProperty<int>(ctx, index, "x");
- *     point.y = duk::getProperty<int>(ctx, index, "y");
- *
- *     return point;
- *   }
- * };
- *
- * }
- * @endcode
- *
- * ## The is function
- *
- * The is function returns a boolean. Again, you decide when the value is appropriate.
- *
- * @code
- *
- * namespace duk {
- *
- * template <>
- * class TypeTraits<Point> {
- * public:
- *   static bool is(ContextPtr ctx, Index index)
- *   {
- *     return is<Object>(ctx, index) && hasProperty(ctx, index, "x") && hasProperty(ctx, index, "y");
- *   }
- * };
- *
- * }
- *
- * @endcode
- *
- * ## The optional function
- *
- * The optional function is like get, you should return a value when it is appropriate for conversion. The
- * recommandation is to return the default value **only if** there is no value at the given index or it it not
- * the correct type.
- *
- * Usual implementation looks like this:
- *
- * @code
- * namespace duk {
- *
- * template <>
- * class TypeTraits<Point> {
- * public:
- *   static Point optional(ContextPtr ctx, Index index, Point def)
- *   {
- *     return is(ctx, index) ? get(ctx, index) : def;
- *   }
- * };
- *
- * }
- * @endcode
- */
-
-/**
- * \page js-more-t2 Advanced 2: exporting C++ class
- * \brief How to export a C++ class through Duktape.
- *
- * This example shows how you can implement a C++ class and export it through C++ through the predefined
- * std::shared_ptr duk::TypeTraits specialization.
- *
- * There are several steps to accomplish this and you must be familiar on how object oriented works in JavaScript.
- *
- * See this [introduction to OO in JavaScript][oojs].
- *
- * \note [RTTI] is required in order to make typesafe binding.
- *
- * ## Ownership
- *
- * To facilitate communication between C++ and JavaScript, objects must be instanciated as `std::shared_ptr`. It
- * guarantees polymorphic objects and ownership.
- *
- * ## The C++ class
- *
- * In that topic, we will implement a basic Car class that has only one drive function, the class must derive from duk::Bindable.
- *
- * @code
- * #include <iostream>
- *
- * #include "js.hpp"
- *
- * class Car : public duk::Binding {
- * public:
- *   void drive()
- *   {
- *     std::cout << "Driving the car..." << std::endl;
- *   }
- * };
- * @endcode
- *
- * ## The JavaScript methods
- *
- * This is the drive method, put it in a map. The method does not take any argument so pass 0.
- *
- * @code
- * duk::Ret drive(duk::ContextPtr ctx)
- * {
- *   duk::self<std::shared_ptr<Car>>(ctx)->drive();
- *
- *   return 0;
- * }
- *
- * const duk::FunctionMap methods{
- *   { "drive", { drive, 0 } }
- * };
- * @endcode
- *
- * ## Construction
- *
- * There are two ways to export a C++ object to JavaScript.
- *
- *   1. When constructed from the JavaScript new operator. You must provide a C function and use duk::construct to
- *      apply your object to it.
- *
- *   2. When pusing from C++ to JavaScript. You muse use Using duk::push and you will need to implement the `prototype`
- *      function in duk::TypeTraits (see below).
- *
- * ## Example 1: provide a constructor for JavaScript ownership
- *
- * This example provides a function to let the user constructing the object **from** JavaScript.
- *
- * ### Add a constructor
- *
- * Add the constructor that will be called from C++.
- *
- * @code
- * duk::Ret constructor(duk::ContextPtr ctx)
- * {
- *   duk::construct(ctx, std::make_shared<Car>());
- *
- *   return 0;
- * }
- * @endcode
- *
- * ### Main
- *
- * We register the constructor, add a prototype and call it from JavaScript.
- *
- * @code
- * int main()
- * {
- *   duk::Context ctx;
- *
- *   // Push the Car constructor function
- *   duk::push(ctx, duk::Function{constructor});
- *
- *   // Push the methods as a new object and set it as the .prototype property
- *   duk::putProperty(ctx, -1, "prototype", methods);
- *
- *   // Now store the Car function
- *   duk::putGlobal(ctx, "Car");
- *
- *   // Create a Car from JavaScript
- *   duk::pevalString(ctx,
- *     "c = new Car();"
- *     "c.drive();"
- *   );
- *
- *   return 0;
- * }
- * @endcode
- *
- * ## Example 2: the object is created from C++
- *
- * This example allocates the Car object from C++ and pass it through JavaScript. It requires to implement the
- * prototype function from duk::TypeTraits.
- *
- * ### Prototype function
- *
- * This function must push into the stack the prototype for the given object. You are free to store it where you want,
- * here, we set it as internal global property.
- *
- * @code
- * namespace duk {
- *
- * template <>
- * class TypeTraits<Car> {
- * public:
- *   static inline void prototype(ContextPtr ctx)
- *   {
- *     getGlobal<void>(ctx, "\xff""\xff""Car-prototype");
- *   }
- * };
- *
- * }
- * @endcode
- *
- * ### Main
- *
- * Now save this prototype and create the object from C++.
- *
- * @code
- * int main()
- * {
- *   duk::Context ctx;
- *
- *   // Create a prototype directly from the methods table (from example 1)
- *   duk::putGlobal(ctx, "\xff""\xff""Car-prototype", methods);
- *
- *   // Put a global Car object
- *   duk::putGlobal(ctx, "car", std::make_shared<Car>());
- *
- *   // Call the JavaScript code
- *   duk::pevalString(ctx, "car.drive();");
- * }
- * @endcode
- *
- * [oojs]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
- * [RTTI]: https://en.wikipedia.org/wiki/Run-time_type_information
- */
-
-/**
- * \page js-concepts Concepts
- *
- * @subpage js-concept-class
- */
-
-/**
- * \page js-concept-class Class (Concept)
- * \brief This concept is used when exporting C++ class through JavaScript.
- *
- * When using `std::shared_ptr<T>` with duk::TypeTraits, the user must implement some function by specializing
- * duk::TypeTraits<T>.
- *
- * ## Public static member functions
- *
- * ### Prototype (optional)
- *
- * The prototype function is optional, it is only required when exporting the C++ object using duk::push. It must push
- * the prototype of your object at the top of the stack.
- *
- * @code
- * static void prototype(duk::ContextPtr ctx);
- * @endcode
- */
-
-#include <cassert>
-#include <functional>
-#include <memory>
-#include <string>
-#include <type_traits>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include <duktape.h>
-
-namespace malikania {
-
-/**
- * Duktape C++ namespace wrapper.
- */
-namespace duk {
-
-class Context;
-
-/**
- * \brief Typedef without pointer.
- */
-using ContextPtr = duk_context *;
-
-/**
- * \brief Typedef for duk_double_t.
- */
-using Double = duk_double_t;
-
-/**
- * \brief Typedef for duk_idx_t.
- */
-using Index = duk_idx_t;
-
-/**
- * \brief Typedef for duk_ret_t.
- */
-using Ret = duk_ret_t;
-
-/**
- * \brief Typedef for duk_int_t.
- */
-using Int = duk_int_t;
-
-/**
- * \brief Typedef for duk_uint_t;
- */
-using Uint = duk_uint_t;
-
-/**
- * \class StackAssert
- * \brief Stack sanity checker.
- *
- * Instanciate this class where you need to manipulate the Duktape stack outside a Duktape/C function, its destructor
- * will examinate if the stack size matches the user expected size.
- *
- * When compiled with NDEBUG, this class does nothing.
- *
- * To use it, just declare an lvalue at the beginning of your function.
- */
-class StackAssert {
-#if !defined(NDEBUG)
-private:
-    ContextPtr m_context;
-    unsigned m_expected;
-    unsigned m_begin;
-#endif
-
-public:
-    /**
-     * Create the stack checker.
-     *
-     * No-op if NDEBUG is set.
-     *
-     * \param ctx the context
-     * \param expected the size expected relative to the already existing values
-     */
-    inline StackAssert(ContextPtr ctx, unsigned expected = 0) noexcept
-#if !defined(NDEBUG)
-        : m_context(ctx)
-        , m_expected(expected)
-        , m_begin(static_cast<unsigned>(duk_get_top(ctx)))
-#endif
-    {
-#if defined(NDEBUG)
-        (void)ctx;
-        (void)expected;
-#endif
-    }
-
-    /**
-     * Verify the expected size.
-     *
-     * No-op if NDEBUG is set.
-     */
-    inline ~StackAssert() noexcept
-    {
-#if !defined(NDEBUG)
-        assert((unsigned)duk_get_top(m_context) - m_begin == m_expected);
-#endif
-    }
-};
-
-/**
- * \brief Inherit this class to make type safe C++ objects into JavaScript
- */
-class Bindable {
-public:
-    /**
-     * Default constructor
-     */
-    Bindable() = default;
-
-    /**
-     * Default destructor.
-     */
-    virtual ~Bindable() = default;
-};
-
-/**
- * \class TypeTraits
- * \brief Type information to implement new types in JavaScript's context.
- *
- * %This class depending on your needs may have the following functions:
- *
- * ## Construct
- *
- * Used by duk::construct, the function must place the value as this binding when the Duktape C function is
- * new-constructed.
- *
- * @code
- * static void construct(ContextPtr ctx, Type value);
- * @endcode
- *
- * ## Get
- *
- * Convert the value at the given index and return it. Should return default object if value is invalid.
- *
- * @code
- * static Type get(ContextPtr ctx, int index);
- * @endcode
- *
- * ## Is
- *
- * Tells if the value at given index is of the requested type.
- *
- * @code
- * static bool is(ContextPtr ctx, int index);
- * @endcode
- *
- * ## Optional
- *
- * Get the value at the given index or return the defaultValue.
- *
- * @code
- * static Type optional(ContextPtr ctx, int index, Type defaultValue);
- * @endcode
- *
- * ## Push
- *
- * Push the value into the stack.
- *
- * @code
- * static void push(ContextPtr ctx, Type value);
- * @endcode
- *
- * ## Put
- *
- * Apply the value to the object at the top of the stack.
- *
- * @code
- * static void put(ContextPtr ctx, Type value);
- * @endcode
- *
- * ## Require
- *
- * Require a value at the given index.
- *
- * @code
- * static Type require(ContextPtr ctx, int index);
- * @endcode
- *
- */
-template <typename Type>
-class TypeTraits;
-
-/**
- * \class Object
- * \brief Special type for duk::TypeTraits.
- */
-class Object {
-};
-
-/**
- * \class Array
- * \brief Special type for duk::TypeTraits.
- */
-class Array {
-};
-
-/**
- * \class Global
- * \brief Special type for duk::TypeTraits.
- */
-class Global {
-};
-
-/**
- * \class Undefined
- * \brief Special type for duk::TypeTraits.
- */
-class Undefined {
-};
-
-/**
- * \class Null
- * \brief Special type for duk::TypeTraits.
- */
-class Null {
-};
-
-/**
- * \class This
- * \brief Special type for duk::TypeTraits.
- */
-class This {
-};
-
-/**
- * \class Function
- * \brief Duktape/C function definition.
- *
- * This class wraps the std::function as a Duktape/C function by storing a copied pointer.
- */
-class Function {
-public:
-    /**
-     * The function pointer, must not be null.
-     */
-    duk_c_function function;
-
-    /**
-     * Number of args that the function takes
-     */
-    duk_idx_t nargs{0};
-};
-
-/**
- * \brief Map of functions.
- */
-using FunctionMap = std::unordered_map<std::string, Function>;
-
-/**
- * \brief Map of any type.
- */
-template <typename T>
-using Map = std::unordered_map<std::string, T>;
-
-/**
- * \class Exception
- * \brief Error description.
- *
- * This class fills the fields got in an Error object.
- */
-class Exception : public std::exception {
-public:
-    std::string name;        //!< name of error
-    std::string message;        //!< error message
-    std::string stack;        //!< stack if available
-    std::string fileName;        //!< filename if applicable
-    int lineNumber{0};        //!< line number if applicable
-
-    /**
-     * Get the error message. This effectively returns message field.
-     *
-     * \return the message
-     */
-    const char *what() const noexcept override
-    {
-        return message.c_str();
-    }
-};
-
-/**
- * \class Context
- * \brief RAII based Duktape handler.
- *
- * This class is implicitly convertible to duk_context for convenience.
- */
-class Context {
-private:
-    using Deleter = void (*)(duk_context *);
-    using Handle = std::unique_ptr<duk_context, Deleter>;
-
-    Handle m_handle;
-
-    Context(const Context &) = delete;
-    Context &operator=(const Context &) = delete;
-
-public:
-    /**
-     * Create default context.
-     */
-    inline Context()
-        : m_handle(duk_create_heap_default(), duk_destroy_heap)
-    {
-    }
-
-    /**
-     * Default move constructor.
-     */
-    Context(Context &&) noexcept = default;
-
-    /**
-     * Convert the context to the native Duktape/C type.
-     *
-     * \return the duk_context
-     */
-    inline operator duk_context *() noexcept
-    {
-        return m_handle.get();
-    }
-
-    /**
-     * Convert the context to the native Duktape/C type.
-     *
-     * \return the duk_context
-     */
-    inline operator duk_context *() const noexcept
-    {
-        return m_handle.get();
-    }
-
-    /**
-     * Default move assignment operator.
-     */
-    Context &operator=(Context &&) noexcept = delete;
-};
-
-/**
- * @name Duktape C functions
- * \brief The following functions are wrappers on top of the Duktape C functions.
- *
- * They are as close as possible to the original functions.
- */
-
-/**
- * @{
- */
-
-/**
- * Wrapper for [duk_base64_decode](http://duktape.org/api.html#duk_base64_decode).
- *
- * \param ctx the context
- * \param index the index
- */
-inline void base64Decode(ContextPtr ctx, Index index)
-{
-    duk_base64_decode(ctx, index);
-}
-
-/**
- * Wrapper for [duk_base64_encode](http://duktape.org/api.html#duk_base64_encode).
- *
- * \param ctx the context
- * \param index the index
- * \return the base64 string
- */
-inline std::string base64Encode(ContextPtr ctx, Index index)
-{
-    return duk_base64_encode(ctx, index);
-}
-
-/**
- * Wrapper for [duk_call](http://duktape.org/api.html#duk_call).
- *
- * \param ctx the context
- * \param nargs the number of arguments
- */
-inline void call(ContextPtr ctx, Index nargs = 0)
-{
-    duk_call(ctx, nargs);
-}
-
-/**
- * Wrapper for [duk_call_method](http://duktape.org/api.html#duk_call_method).
- *
- * \param ctx the context
- * \param nargs the number of arguments
- */
-inline void callMethod(ContextPtr ctx, Index nargs = 0)
-{
-    duk_call_method(ctx, nargs);
-}
-
-/**
- * Wrapper for [duk_call_prop](http://duktape.org/api.html#duk_call_prop).
- *
- * \param ctx the context
- * \param index the object index
- * \param nargs the number of arguments
- */
-inline void callProperty(ContextPtr ctx, Index index, Index nargs = 0)
-{
-    duk_call_prop(ctx, index, nargs);
-}
-
-/**
- * Wrapper for [duk_char_code_at](http://duktape.org/api.html#duk_char_code_at).
- *
- * \param ctx the context
- * \param index the index
- * \param charOffset the offset
- */
-inline duk_codepoint_t charCodeAt(ContextPtr ctx, Index index, duk_size_t charOffset)
-{
-    return duk_char_code_at(ctx, index, charOffset);
-}
-
-/**
- * Wrapper for [duk_check_stack](http://duktape.org/api.html#duk_check_stack).
- *
- * \param ctx the context
- * \param extra the extra space
- * \return true if space is available
- */
-inline bool checkStack(ContextPtr ctx, Index extra)
-{
-    return duk_check_stack(ctx, extra);
-}
-
-/**
- * Wrapper for [duk_check_stack_top](http://duktape.org/api.html#duk_check_stack_top).
- *
- * \param ctx the context
- * \param top the extra space
- * \return true if space is available
- */
-inline bool checkStackTop(ContextPtr ctx, Index top)
-{
-    return duk_check_stack_top(ctx, top);
-}
-
-/**
- * Wrapper for [duk_check_type](http://duktape.org/api.html#duk_check_type).
- *
- * \param ctx the context
- * \param index the value index
- * \param type the desired type
- * \return true if object is given type
- */
-inline bool checkType(ContextPtr ctx, Index index, int type)
-{
-    return duk_check_type(ctx, index, type);
-}
-
-/**
- * Wrapper for [duk_check_type_mask](http://duktape.org/api.html#duk_check_type_mask).
- *
- * \param ctx the context
- * \param index the value index
- * \param mask the desired mask
- * \return true if object is one of the type
- */
-inline bool checkTypeMask(ContextPtr ctx, Index index, unsigned mask)
-{
-    return duk_check_type_mask(ctx, index, mask);
-}
-
-/**
- * Wrapper for [duk_compact](http://duktape.org/api.html#duk_compact).
- *
- * \param ctx the context
- * \param objIndex the object index
- */
-inline void compact(ContextPtr ctx, Index objIndex)
-{
-    duk_compact(ctx, objIndex);
-}
-
-/**
- * Wrapper for [duk_concat](http://duktape.org/api.html#duk_concat).
- *
- * \param ctx the context
- * \param count the number of values
- */
-inline void concat(ContextPtr ctx, Index count)
-{
-    duk_concat(ctx, count);
-}
-
-/**
- * Wrapper for [duk_copy](http://duktape.org/api.html#duk_copy).
- *
- * \param ctx the context
- * \param from the from index
- * \param to the destination
- */
-inline void copy(ContextPtr ctx, Index from, Index to)
-{
-    duk_copy(ctx, from, to);
-}
-
-/**
- * Wrapper for [duk_new](http://duktape.org/api.html#duk_new).
- *
- * \param ctx the context
- * \param nargs the number of arguments
- */
-inline void create(ContextPtr ctx, int nargs = 0)
-{
-    duk_new(ctx, nargs);
-}
-
-/**
- * Wrapper for [duk_def_prop](http://duktape.org/api.html#duk_def_prop).
- *
- * \param ctx the context
- * \param index the object index
- * \param flags the flags
- */
-inline void defineProperty(ContextPtr ctx, Index index, unsigned flags)
-{
-    duk_def_prop(ctx, index, flags);
-}
-
-/**
- * Wrapper for [duk_del_prop](http://duktape.org/api.html#duk_del_prop).
- *
- * \param ctx the context
- * \param index the object index
- * \return true if deleted
- */
-inline bool deleteProperty(ContextPtr ctx, Index index)
-{
-    return duk_del_prop(ctx, index);
-}
-
-/**
- * Wrapper for [duk_del_prop](http://duktape.org/api.html#duk_del_prop).
- *
- * \param ctx the context
- * \param index the object index
- * \param position the property index
- * \return true if deleted
- */
-inline bool deleteProperty(ContextPtr ctx, Index index, unsigned position)
-{
-    return duk_del_prop_index(ctx, index, position);
-}
-
-/**
- * Wrapper for [duk_del_prop](http://duktape.org/api.html#duk_del_prop).
- *
- * \param ctx the context
- * \param index the object index
- * \param name the property name
- * \return true if deleted
- */
-inline bool deleteProperty(ContextPtr ctx, Index index, const std::string &name)
-{
-    return duk_del_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Wrapper for [duk_dup](http://duktape.org/api.html#duk_dup).
- *
- * \param ctx the context
- * \param index the value to copy
- */
-inline void dup(ContextPtr ctx, int index = -1)
-{
-    duk_dup(ctx, index);
-}
-
-/**
- * Wrapper for [duk_equals](http://duktape.org/api.html#duk_equals).
- *
- * \param ctx the context
- * \param index1 the first value
- * \param index2 the second value
- * \return true if they equal
- */
-inline bool equals(ContextPtr ctx, Index index1, Index index2)
-{
-    return duk_equals(ctx, index1, index2);
-}
-
-/**
- * Wrapper for [duk_eval](http://duktape.org/api.html#duk_eval).
- *
- * \param ctx the context
- */
-inline void eval(ContextPtr ctx)
-{
-    duk_eval(ctx);
-}
-
-/**
- * Wrapper for [duk_eval_file](http://duktape.org/api.html#duk_eval_file).
- *
- * \param ctx the context
- * \param path the path
- * \param result true to get the result at the top of the stack
- */
-inline void evalFile(ContextPtr ctx, const std::string &path, bool result = true)
-{
-    if (result)
-        duk_eval_file(ctx, path.c_str());
-    else
-        duk_eval_file_noresult(ctx, path.c_str());
-}
-
-/**
- * Wrapper for [duk_eval_string](http://duktape.org/api.html#duk_eval_string).
- *
- * \param ctx the context
- * \param src the source script
- * \param result true to get the result at the top of the stack
- */
-inline void evalString(ContextPtr ctx, const std::string &src, bool result = true)
-{
-    if (result)
-        duk_eval_string(ctx, src.c_str());
-    else
-        duk_eval_string_noresult(ctx, src.c_str());
-}
-/**
- * Wrapper for [duk_gc](http://duktape.org/api.html#duk_gc).
- *
- * \param ctx the context
- * \param flags the flags
- */
-inline void gc(ContextPtr ctx, unsigned flags = 0)
-{
-    duk_gc(ctx, flags);
-}
-
-/**
- * Wrapper for [duk_has_prop](http://duktape.org/api.html#duk_has_prop).
- *
- * \param ctx the context
- * \param index the object index
- * \return true if has
- */
-inline bool hasProperty(ContextPtr ctx, Index index)
-{
-    return duk_has_prop(ctx, index);
-}
-
-/**
- * Wrapper for [duk_has_prop](http://duktape.org/api.html#duk_has_prop).
- *
- * \param ctx the context
- * \param index the object index
- * \param position the property index
- * \return true if has
- */
-inline bool hasProperty(ContextPtr ctx, Index index, unsigned position)
-{
-    return duk_has_prop_index(ctx, index, position);
-}
-
-/**
- * Wrapper for [duk_has_prop](http://duktape.org/api.html#duk_has_prop).
- *
- * \param ctx the context
- * \param index the object index
- * \param name the property name
- * \return true if has
- */
-inline bool hasProperty(ContextPtr ctx, int index, const std::string &name)
-{
-    return duk_has_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Wrapper for [duk_insert](http://duktape.org/api.html#duk_insert).
- *
- * \param ctx the context
- * \param to the destination
- * \note Wrapper of duk_insert
- */
-inline void insert(ContextPtr ctx, Index to)
-{
-    duk_insert(ctx, to);
-}
-
-/**
- * Wrapper for [duk_instanceof](http://duktape.org/api.html#duk_instanceof).
- *
- * \param ctx the context
- * \param idx1 the value to test
- * \param idx2 the instance requested
- * \return true if idx1 is instance of idx2
- */
-inline bool instanceof(ContextPtr ctx, Index idx1, Index idx2)
-{
-    return duk_instanceof(ctx, idx1, idx2);
-}
-
-/**
- * Wrapper for [duk_join](http://duktape.org/api.html#duk_join).
- *
- * \param ctx the context
- * \param count the number of values
- */
-inline void join(ContextPtr ctx, Index count)
-{
-    duk_join(ctx, count);
-}
-
-/**
- * Wrapper for [duk_json_decode](http://duktape.org/api.html#duk_json_decode).
- *
- * \param ctx the context
- * \param index the index
- */
-inline void jsonDecode(ContextPtr ctx, Index index)
-{
-    duk_json_decode(ctx, index);
-}
-
-/**
- * Wrapper for [duk_json_encode](http://duktape.org/api.html#duk_json_encode).
- *
- * \param ctx the context
- * \param index the index
- * \return the JSON string
- */
-inline std::string jsonEncode(ContextPtr ctx, Index index)
-{
-    return duk_json_encode(ctx, index);
-}
-
-/**
- * Wrapper for [duk_normalize_index](http://duktape.org/api.html#duk_normalize_index).
- *
- * \param ctx the context
- * \param index the index
- */
-inline Index normalizeIndex(ContextPtr ctx, Index index)
-{
-    return duk_normalize_index(ctx, index);
-}
-
-/**
- * Wrapper for [duk_pcall](http://duktape.org/api.html#duk_pcall).
- *
- * \param ctx the context
- * \param nargs the number of arguments
- */
-inline int pcall(ContextPtr ctx, Index nargs = 0)
-{
-    return duk_pcall(ctx, nargs);
-}
-
-/**
- * Wrapper for [duk_pcall_method](http://duktape.org/api.html#duk_pcall_method).
- *
- * \param ctx the context
- * \param nargs the number of arguments
- */
-inline int pcallMethod(ContextPtr ctx, Index nargs = 0)
-{
-    return duk_pcall_method(ctx, nargs);
-}
-
-/**
- * Wrapper for [duk_pcall_prop](http://duktape.org/api.html#duk_pcall_prop).
- *
- * \param ctx the context
- * \param index the object index
- * \param nargs the number of arguments
- */
-inline int pcallProperty(ContextPtr ctx, Index index, Index nargs = 0)
-{
-    return duk_pcall_prop(ctx, index, nargs);
-}
-
-/**
- * Wrapper for [duk_peval](http://duktape.org/api.html#duk_peval).
- *
- * \param ctx the context
- */
-inline int peval(ContextPtr ctx)
-{
-    return duk_peval(ctx);
-}
-
-/**
- * Wrapper for [duk_peval_file](http://duktape.org/api.html#duk_peval_file).
- *
- * \param ctx the context
- * \param path the path
- * \param result true to get the result at the top of the stack
- */
-inline int pevalFile(ContextPtr ctx, const std::string &path, bool result = true)
-{
-    return result ? duk_peval_file(ctx, path.c_str()) : duk_peval_file_noresult(ctx, path.c_str());
-}
-
-/**
- * Wrapper for [duk_peval_string](http://duktape.org/api.html#duk_peval_string).
- *
- * \param ctx the context
- * \param src the source script
- * \param result true to get the result at the top of the stack
- */
-inline int pevalString(ContextPtr ctx, const std::string &src, bool result = true)
-{
-    return result ? duk_peval_string(ctx, src.c_str()) : duk_peval_string_noresult(ctx, src.c_str());
-}
-
-/**
- * Wrapper for [duk_pop_n](http://duktape.org/api.html#duk_pop_n).
- *
- * \param ctx the context
- * \param count the number of values to pop
- */
-inline void pop(ContextPtr ctx, Index count = 1)
-{
-    duk_pop_n(ctx, count);
-}
-
-/**
- * Wrapper for [duk_put_prop](http://duktape.org/api.html#duk_put_prop).
- *
- * \param ctx the context
- * \param index the object index
- */
-inline void putProperty(ContextPtr ctx, Index index)
-{
-    duk_put_prop(ctx, index);
-}
-
-/**
- * Wrapper for [duk_put_prop_string](http://duktape.org/api.html#duk_put_prop_string).
- *
- * \param ctx the context
- * \param index the object index
- * \param name the property name
- */
-inline void putProperty(ContextPtr ctx, Index index, const std::string &name)
-{
-    duk_put_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Wrapper for [duk_put_prop_index](http://duktape.org/api.html#duk_put_prop_index).
- *
- * \param ctx the context
- * \param index the object index
- * \param position the array position
- */
-inline void putProperty(ContextPtr ctx, Index index, unsigned position)
-{
-    duk_put_prop_index(ctx, index, position);
-}
-
-/**
- * Wrapper for [duk_remove](http://duktape.org/api.html#duk_remove).
- *
- * \param ctx the context
- * \param index the value to remove
- */
-inline void remove(ContextPtr ctx, Index index)
-{
-    duk_remove(ctx, index);
-}
-
-/**
- * Wrapper for [duk_replace](http://duktape.org/api.html#duk_replace).
- *
- * \param ctx the context
- * \param index the value to replace by the value at the top of the stack
- */
-inline void replace(ContextPtr ctx, Index index)
-{
-    duk_replace(ctx, index);
-}
-
-/**
- * Wrapper for [duk_set_prototype](http://duktape.org/api.html#duk_set_prototype).
- *
- * \param ctx the context
- * \param index the value index
- */
-inline void setPrototype(ContextPtr ctx, Index index)
-{
-    duk_set_prototype(ctx, index);
-}
-
-/**
- * Wrapper for [duk_swap](http://duktape.org/api.html#duk_swap).
- *
- * \param ctx the context
- * \param index1 the first index
- * \param index2 the second index
- */
-inline void swap(ContextPtr ctx, Index index1, Index index2)
-{
-    duk_swap(ctx, index1, index2);
-}
-
-/**
- * Wrapper for [duk_swap_top](http://duktape.org/api.html#duk_swap_top).
- *
- * \param ctx the context
- * \param index the index
- */
-inline void swapTop(ContextPtr ctx, Index index)
-{
-    duk_swap_top(ctx, index);
-}
-
-/**
- * Wrapper for [duk_get_top](http://duktape.org/api.html#duk_get_top).
- *
- * \param ctx the context
- * \return the stack size
- */
-inline int top(ContextPtr ctx)
-{
-    return duk_get_top(ctx);
-}
-
-/**
- * Wrapper for [duk_throw](http://duktape.org/api.html#duk_throw).
- *
- * \param ctx the context
- */
-inline void raise(ContextPtr ctx)
-{
-    duk_throw(ctx);
-}
-
-/**
- *Wrapper for [duk_error](http://duktape.org/api.html#duk_error).
- *
- * \param ctx the context
- * \param type the error type (e.g. DUK_ERR_REFERENCE_ERROR)
- * \param fmt the format string
- * \param args the arguments
- */
-template <typename... Args>
-inline void raise(ContextPtr ctx, int type, const char *fmt, Args&&... args)
-{
-    duk_error(ctx, type, fmt, std::forward<Args>(args)...);
-}
-
-/**
- * Wrapper for [duk_get_type](http://duktape.org/api.html#duk_get_type).
- *
- * \param ctx the context
- * \param index the idnex
- * \return the type
- */
-inline int type(ContextPtr ctx, Index index)
-{
-    return duk_get_type(ctx, index);
-}
-
-/**
- * @}
- */
-
-/**
- * @name Extended functions
- * \brief Extended functions for libjs.
- *
- * The following functions are largely modified or extensions to Duktape.
- */
-
-/**
- * @{
- */
-
-/**
- * Get the error object when a JavaScript error has been thrown (e.g. eval failure).
- *
- * \param ctx the context
- * \param index the index
- * \return the information
- */
-inline Exception exception(ContextPtr ctx, int index)
-{
-    Exception ex;
-    StackAssert sa(ctx);
-
-    index = duk_normalize_index(ctx, index);
-
-    duk_get_prop_string(ctx, index, "name");
-    ex.name = duk_to_string(ctx, -1);
-    duk_get_prop_string(ctx, index, "message");
-    ex.message = duk_to_string(ctx, -1);
-    duk_get_prop_string(ctx, index, "fileName");
-    ex.fileName = duk_to_string(ctx, -1);
-    duk_get_prop_string(ctx, index, "lineNumber");
-    ex.lineNumber = duk_to_int(ctx, -1);
-    duk_get_prop_string(ctx, index, "stack");
-    ex.stack = duk_to_string(ctx, -1);
-    duk_pop_n(ctx, 5);
-
-    return ex;
-}
-
-/**
- * Push a value into the stack. Calls TypeTraits<T>::push(ctx, value);
- *
- * \param ctx the context
- * \param value the value to forward
- */
-template <typename Type>
-inline void push(ContextPtr ctx, Type &&value)
-{
-    TypeTraits<std::decay_t<Type>>::push(ctx, std::forward<Type>(value));
-}
-
-/**
- * Put the value to the object at the top of the stack. Calls TypeTraits<T>::put(ctx, value);
- *
- * \param ctx the context
- * \param value the value to apply
- */
-template <typename Type>
-inline void put(ContextPtr ctx, Type &&value)
-{
-    TypeTraits<std::decay_t<Type>>::put(ctx, std::forward<Type>(value));
-}
-
-/**
- * Generic template function to get a value from the stack.
- *
- * \param ctx the context
- * \param index the index
- * \return the value
- */
-template <typename Type>
-inline auto get(ContextPtr ctx, int index) -> decltype(TypeTraits<Type>::get(ctx, 0))
-{
-    return TypeTraits<Type>::get(ctx, index);
-}
-
-/**
- * Require a type at the specified index.
- *
- * \param ctx the context
- * \param index the index
- * \return the value
- */
-template <typename Type>
-inline auto require(ContextPtr ctx, int index) -> decltype(TypeTraits<Type>::require(ctx, 0))
-{
-    return TypeTraits<Type>::require(ctx, index);
-}
-
-/**
- * Check if a value is a type of T.
- *
- * The TypeTraits<T> must have `static bool is(ContextPtr ptr, int index)`.
- *
- * \param ctx the context
- * \param index the value index
- * \return true if is the type
- */
-template <typename T>
-inline bool is(ContextPtr ctx, int index)
-{
-    return TypeTraits<T>::is(ctx, index);
-}
-
-/**
- * Get an optional value from the stack, if the value is not available of not the correct type,
- * return defaultValue instead.
- *
- * The TypeTraits<T> must have `static T optional(Context &, int index, T &&defaultValue)`.
- *
- * \param ctx the context
- * \param index the value index
- * \param defaultValue the value replacement
- * \return the value or defaultValue
- */
-template <typename Type>
-inline auto optional(ContextPtr ctx, int index, Type &&defaultValue)
-{
-    return TypeTraits<std::decay_t<Type>>::optional(ctx, index, std::forward<Type>(defaultValue));
-}
-
-/**
- * Get the property `name' as value from the object at the specified index.
- *
- * \param ctx the context
- * \param index the object index
- * \param name the property name
- * \return the value
- * \note The stack is unchanged
- */
-template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
-inline auto getProperty(ContextPtr ctx, int index, const std::string &name) -> decltype(get<Type>(ctx, 0))
-{
-    duk_get_prop_string(ctx, index, name.c_str());
-    decltype(get<Type>(ctx, 0)) value = get<Type>(ctx, -1);
-    duk_pop(ctx);
-
-    return value;
-}
-
-/**
- * Get a property by index, for arrays.
- *
- * \param ctx the context
- * \param index the object index
- * \param position the position int the object
- * \return the value
- * \note The stack is unchanged
- */
-template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
-inline auto getProperty(ContextPtr ctx, int index, int position) -> decltype(get<Type>(ctx, 0))
-{
-    duk_get_prop_index(ctx, index, position);
-    decltype(get<Type>(ctx, 0)) value = get<Type>(ctx, -1);
-    duk_pop(ctx);
-
-    return value;
-}
-
-/**
- * Get the property `name' and push it to the stack from the object at the specified index.
- *
- * \param ctx the context
- * \param index the object index
- * \param name the property name
- * \note The stack contains the property value
- */
-template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
-inline void getProperty(ContextPtr ctx, int index, const std::string &name)
-{
-    duk_get_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Get the property by index and push it to the stack from the object at the specified index.
- *
- * \param ctx the context
- * \param index the object index
- * \param position the position in the object
- * \note The stack contains the property value
- */
-template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
-inline void getProperty(ContextPtr ctx, int index, int position)
-{
-    duk_get_prop_index(ctx, index, position);
-}
-
-/**
- * Get an optional property `name` from the object at the specified index.
- *
- * \param ctx the context
- * \param index the object index
- * \param name the property name
- * \param def the default value
- * \return the value or def
- * \note The stack is unchanged
- */
-template <typename Type, typename DefaultValue>
-inline auto optionalProperty(ContextPtr ctx, int index, const std::string &name, DefaultValue &&def) -> decltype(optional(ctx, 0, std::forward<DefaultValue>(def)))
-{
-    duk_get_prop_string(ctx, index, name.c_str());
-    decltype(optional(ctx, 0, std::forward<DefaultValue>(def))) value = optional(ctx, -1, std::forward<DefaultValue>(def));
-    duk_pop(ctx);
-
-    return value;
-}
-
-/**
- * Get an optional property by index, for arrays
- *
- * \param ctx the context
- * \param index the object index
- * \param position the position int the object
- * \param def the default value
- * \return the value or def
- * \note The stack is unchanged
- */
-template <typename Type, typename DefaultValue>
-inline auto optionalProperty(ContextPtr ctx, int index, int position, DefaultValue &&def) -> decltype(optional(ctx, 0, std::forward<DefaultValue>(def)))
-{
-    duk_get_prop_index(ctx, index, position);
-    decltype(optional(ctx, 0, std::forward<DefaultValue>(def))) value = optional(ctx, -1, std::forward<DefaultValue>(def));
-    duk_pop(ctx);
-
-    return value;
-}
-
-/**
- * Set a property to the object at the specified index.
- *
- * \param ctx the context
- * \param index the object index
- * \param name the property name
- * \param value the value to forward
- * \note The stack is unchanged
- */
-template <typename Type>
-void putProperty(ContextPtr ctx, int index, const std::string &name, Type &&value)
-{
-    index = duk_normalize_index(ctx, index);
-
-    push(ctx, std::forward<Type>(value));
-    duk_put_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Set a property by index, for arrays.
- *
- * \param ctx the context
- * \param index the object index
- * \param position the position in the object
- * \param value the value to forward
- * \note The stack is unchanged
- */
-template <typename Type>
-void putProperty(ContextPtr ctx, int index, int position, Type &&value)
-{
-    index = duk_normalize_index(ctx, index);
-
-    push(ctx, std::forward<Type>(value));
-    duk_put_prop_index(ctx, index, position);
-}
-
-/**
- * Get a global value.
- *
- * \param ctx the context
- * \param name the name of the global variable
- * \return the value
- */
-template <typename Type>
-inline auto getGlobal(ContextPtr ctx, const std::string &name, std::enable_if_t<!std::is_void<Type>::value> * = nullptr) -> decltype(get<Type>(ctx, 0))
-{
-    duk_get_global_string(ctx, name.c_str());
-    decltype(get<Type>(ctx, 0)) value = get<Type>(ctx, -1);
-    duk_pop(ctx);
-
-    return value;
-}
-
-/**
- * Overload that push the value at the top of the stack instead of returning it.
- */
-template <typename Type>
-inline void getGlobal(ContextPtr ctx, const std::string &name, std::enable_if_t<std::is_void<Type>::value> * = nullptr)
-{
-    duk_get_global_string(ctx, name.c_str());
-}
-
-/**
- * Set a global variable.
- *
- * \param ctx the context
- * \param name the name of the global variable
- * \param type the value to set
- */
-template <typename Type>
-inline void putGlobal(ContextPtr ctx, const std::string &name, Type&& type)
-{
-    push(ctx, std::forward<Type>(type));
-    duk_put_global_string(ctx, name.c_str());
-}
-
-/**
- * Put the value at the top of the stack as global property.
- *
- * \param ctx the context
- * \param name the property name
- */
-inline void putGlobal(ContextPtr ctx, const std::string &name)
-{
-    duk_put_global_string(ctx, name.c_str());
-}
-
-/**
- * Enumerate an object or an array at the specified index.
- *
- * \param ctx the context
- * \param index the object or array index
- * \param flags the optional flags to pass to duk_enum
- * \param getvalue set to true if you want to extract the value
- * \param func the function to call for each properties
- */
-template <typename Func>
-void enumerate(ContextPtr ctx, int index, duk_uint_t flags, duk_bool_t getvalue, Func &&func)
-{
-    duk_enum(ctx, index, flags);
-
-    while (duk_next(ctx, -1, getvalue)) {
-        func(ctx);
-        duk_pop_n(ctx, 1 + (getvalue ? 1 : 0));
-    }
-
-    duk_pop(ctx);
-}
-
-/**
- * Return the this binding of the current function.
- *
- * \param ctx the context
- * \return the this binding as the template given
- */
-template <typename T>
-inline auto self(ContextPtr ctx) -> decltype(TypeTraits<T>::require(ctx, 0))
-{
-    duk_push_this(ctx);
-    decltype(TypeTraits<T>::require(ctx, 0)) value = TypeTraits<T>::require(ctx, -1);
-    duk_pop(ctx);
-
-    return value;
-}
-
-/**
- * Throw an ECMAScript exception.
- *
- * \param ctx the context
- * \param ex the exception
- */
-template <typename Exception>
-void raise(ContextPtr ctx, const Exception &ex)
-{
-    ex.raise(ctx);
-}
-
-/**
- * Construct the object in place, setting value as this binding.
- *
- * The TypeTraits<T> must have the following requirements:
- *
- * - static void construct(Context &, T): must update this with the value and keep the stack unchanged
- *
- * \param ctx the context
- * \param value the value to forward
- * \see self
- */
-template <typename T>
-inline void construct(ContextPtr ctx, T &&value)
-{
-    TypeTraits<std::decay_t<T>>::construct(ctx, std::forward<T>(value));
-}
-
-/**
- * @}
- */
-
-/**
- * \class Error
- * \brief Base ECMAScript error class.
- * \warning Override the function create for your own exceptions
- */
-class Error {
-private:
-    int m_type{DUK_ERR_ERROR};
-    std::string m_message;
-
-protected:
-    /**
-     * Constructor with a type of error specified, specially designed for derived errors.
-     *
-     * \param type of error (e.g. DUK_ERR_ERROR)
-     * \param message the message
-     */
-    inline Error(int type, std::string message) noexcept
-        : m_type(type)
-        , m_message(std::move(message))
-    {
-    }
-
-public:
-    /**
-     * Constructor with a message.
-     *
-     * \param message the message
-     */
-    inline Error(std::string message) noexcept
-        : m_message(std::move(message))
-    {
-    }
-
-    /**
-     * Create the exception on the stack.
-     *
-     * \note the default implementation search for the global variables
-     * \param ctx the context
-     */
-    virtual void raise(ContextPtr ctx) const
-    {
-        duk_error(ctx, m_type, "%s", m_message.c_str());
-    }
-};
-
-/**
- * \class EvalError
- * \brief Error in eval() function.
- */
-class EvalError : public Error {
-public:
-    /**
-     * Construct an EvalError.
-     *
-     * \param message the message
-     */
-    inline EvalError(std::string message) noexcept
-        : Error(DUK_ERR_EVAL_ERROR, std::move(message))
-    {
-    }
-};
-
-/**
- * \class RangeError
- * \brief Value is out of range.
- */
-class RangeError : public Error {
-public:
-    /**
-     * Construct an RangeError.
-     *
-     * \param message the message
-     */
-    inline RangeError(std::string message) noexcept
-        : Error(DUK_ERR_RANGE_ERROR, std::move(message))
-    {
-    }
-};
-
-/**
- * \class ReferenceError
- * \brief Trying to use a variable that does not exist.
- */
-class ReferenceError : public Error {
-public:
-    /**
-     * Construct an ReferenceError.
-     *
-     * \param message the message
-     */
-    inline ReferenceError(std::string message) noexcept
-        : Error(DUK_ERR_REFERENCE_ERROR, std::move(message))
-    {
-    }
-};
-
-/**
- * \class SyntaxError
- * \brief Syntax error in the script.
- */
-class SyntaxError : public Error {
-public:
-    /**
-     * Construct an SyntaxError.
-     *
-     * \param message the message
-     */
-    inline SyntaxError(std::string message) noexcept
-        : Error(DUK_ERR_SYNTAX_ERROR, std::move(message))
-    {
-    }
-};
-
-/**
- * \class TypeError
- * \brief Invalid type given.
- */
-class TypeError : public Error {
-public:
-    /**
-     * Construct an TypeError.
-     *
-     * \param message the message
-     */
-    inline TypeError(std::string message) noexcept
-        : Error(DUK_ERR_TYPE_ERROR, std::move(message))
-    {
-    }
-};
-
-/**
- * \class URIError
- * \brief URI manipulation failure.
- */
-class URIError : public Error {
-public:
-    /**
-     * Construct an URIError.
-     *
-     * \param message the message
-     */
-    inline URIError(std::string message) noexcept
-        : Error(DUK_ERR_URI_ERROR, std::move(message))
-    {
-    }
-};
-
-/* ------------------------------------------------------------------
- * Standard overloads for TypeTraits<T>
- * ------------------------------------------------------------------ */
-
-/**
- * \class TypeTraits<int>
- * \brief Default implementation for int.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeTraits<int> {
-public:
-    /**
-     * Get an integer, return 0 if not an integer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the integer
-     */
-    static inline int get(ContextPtr ctx, int index)
-    {
-        return duk_get_int(ctx, index);
-    }
-
-    /**
-     * Check if value is an integer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if integer
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_number(ctx, index);
-    }
-
-    /**
-     * Get an integer, return defaultValue if the value is not an integer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \param defaultValue the defaultValue
-     * \return the integer or defaultValue
-     */
-    static inline int optional(ContextPtr ctx, int index, int defaultValue)
-    {
-        return is(ctx, index) ? get(ctx, index) : defaultValue;
-    }
-
-    /**
-     * Push an integer.
-     *
-     * \param ctx the context
-     * \param value the value
-     */
-    static inline void push(ContextPtr ctx, int value)
-    {
-        duk_push_int(ctx, value);
-    }
-
-    /**
-     * Require an integer, throws a JavaScript exception if not an integer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the integer
-     */
-    static inline int require(ContextPtr ctx, int index)
-    {
-        return duk_require_int(ctx, index);
-    }
-};
-
-/**
- * \class TypeTraits<bool>
- * \brief Default implementation for bool.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeTraits<bool> {
-public:
-    /**
-     * Get a boolean, return 0 if not a boolean.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the boolean
-     */
-    static inline bool get(ContextPtr ctx, int index)
-    {
-        return duk_get_boolean(ctx, index);
-    }
-
-    /**
-     * Check if value is a boolean.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if boolean
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_boolean(ctx, index);
-    }
-
-    /**
-     * Get a bool, return defaultValue if the value is not a boolean.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \param defaultValue the defaultValue
-     * \return the boolean or defaultValue
-     */
-    static inline bool optional(ContextPtr ctx, int index, bool defaultValue)
-    {
-        return is(ctx, index) ? get(ctx, index) : defaultValue;
-    }
-
-    /**
-     * Push a boolean.
-     *
-     * \param ctx the context
-     * \param value the value
-     */
-    static inline void push(ContextPtr ctx, bool value)
-    {
-        duk_push_boolean(ctx, value);
-    }
-
-    /**
-     * Require a boolean, throws a JavaScript exception if not a boolean.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the boolean
-     */
-    static inline bool require(ContextPtr ctx, int index)
-    {
-        return duk_require_boolean(ctx, index);
-    }
-};
-
-/**
- * \class TypeTraits<double>
- * \brief Default implementation for double.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeTraits<double> {
-public:
-    /**
-     * Get a double, return 0 if not a double.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the double
-     */
-    static inline double get(ContextPtr ctx, int index)
-    {
-        return duk_get_number(ctx, index);
-    }
-
-    /**
-     * Check if value is a double.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if double
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_number(ctx, index);
-    }
-
-    /**
-     * Get a double, return defaultValue if the value is not a double.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \param defaultValue the defaultValue
-     * \return the double or defaultValue
-     */
-    static inline double optional(ContextPtr ctx, int index, double defaultValue)
-    {
-        return is(ctx, index) ? get(ctx, index) : defaultValue;
-    }
-
-    /**
-     * Push a double.
-     *
-     * \param ctx the context
-     * \param value the value
-     */
-    static inline void push(ContextPtr ctx, double value)
-    {
-        duk_push_number(ctx, value);
-    }
-
-    /**
-     * Require a double, throws a JavaScript exception if not a double.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the double
-     */
-    static inline double require(ContextPtr ctx, int index)
-    {
-        return duk_require_number(ctx, index);
-    }
-};
-
-/**
- * \class TypeTraits<std::string>
- * \brief Default implementation for std::string.
- *
- * Provides: get, is, optional, push, require.
- *
- * Note: the functions allows embedded '\0'.
- */
-template <>
-class TypeTraits<std::string> {
-public:
-    /**
-     * Get a string, return 0 if not a string.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the string
-     */
-    static inline std::string get(ContextPtr ctx, int index)
-    {
-        duk_size_t size;
-        const char *text = duk_get_lstring(ctx, index, &size);
-
-        return std::string{text, size};
-    }
-
-    /**
-     * Check if value is a string.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if string
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_string(ctx, index);
-    }
-
-    /**
-     * Get a string, return defaultValue if the value is not an string.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \param defaultValue the defaultValue
-     * \return the string or defaultValue
-     */
-    static inline std::string optional(ContextPtr ctx, int index, std::string defaultValue)
-    {
-        return is(ctx, index) ? get(ctx, index) : defaultValue;
-    }
-
-    /**
-     * Push a string.
-     *
-     * \param ctx the context
-     * \param value the value
-     */
-    static inline void push(ContextPtr ctx, const std::string &value)
-    {
-        duk_push_lstring(ctx, value.c_str(), value.length());
-    }
-
-    /**
-     * Require a string, throws a JavaScript exception if not a string.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the string
-     */
-    static inline std::string require(ContextPtr ctx, int index)
-    {
-        duk_size_t size;
-        const char *text = duk_require_lstring(ctx, index, &size);
-
-        return std::string{text, size};
-    }
-};
-
-/**
- * \class TypeTraits<const char *>
- * \brief Default implementation for const char literals.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeTraits<const char *> {
-public:
-    /**
-     * Get a string, return 0 if not a string.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the string
-     */
-    static inline const char *get(ContextPtr ctx, int index)
-    {
-        return duk_get_string(ctx, index);
-    }
-
-    /**
-     * Check if value is a string.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if string
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_string(ctx, index);
-    }
-
-    /**
-     * Get an integer, return defaultValue if the value is not an integer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \param defaultValue the defaultValue
-     * \return the integer or defaultValue
-     */
-    static inline const char *optional(ContextPtr ctx, int index, const char *defaultValue)
-    {
-        return is(ctx, index) ? get(ctx, index) : defaultValue;
-    }
-
-    /**
-     * Push a string.
-     *
-     * \param ctx the context
-     * \param value the value
-     */
-    static inline void push(ContextPtr ctx, const char *value)
-    {
-        duk_push_string(ctx, value);
-    }
-
-    /**
-     * Require a string, throws a JavaScript exception if not a string.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the string
-     */
-    static inline const char *require(ContextPtr ctx, int index)
-    {
-        return duk_require_string(ctx, index);
-    }
-};
-
-/**
- * \class TypeTraits<unsigned>
- * \brief Default implementation for unsigned.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeTraits<unsigned> {
-public:
-    /**
-     * Get an integer, return 0 if not an integer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the integer
-     */
-    static inline unsigned get(ContextPtr ctx, int index)
-    {
-        return duk_get_uint(ctx, index);
-    }
-
-    /**
-     * Check if value is an integer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if integer
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_number(ctx, index);
-    }
-
-    /**
-     * Get an integer, return defaultValue if the value is not an integer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \param defaultValue the defaultValue
-     * \return the integer or defaultValue
-     */
-    static inline unsigned optional(ContextPtr ctx, int index, unsigned defaultValue)
-    {
-        return is(ctx, index) ? get(ctx, index) : defaultValue;
-    }
-
-    /**
-     * Push an integer.
-     *
-     * \param ctx the context
-     * \param value the value
-     */
-    static inline void push(ContextPtr ctx, unsigned value)
-    {
-        duk_push_uint(ctx, value);
-    }
-
-    /**
-     * Require an integer, throws a JavaScript exception if not an integer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the integer
-     */
-    static inline unsigned require(ContextPtr ctx, int index)
-    {
-        return duk_require_uint(ctx, index);
-    }
-};
-
-/**
- * \brief Implementation for non-managed pointers.
- *
- * Provides: get, is, optional, push, require.
- */
-template <typename T>
-class TypeTraits<T *> {
-public:
-    /**
-     * Get a pointer, return nullptr if not a pointer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the pointer
-     */
-    static inline T *get(ContextPtr ctx, int index)
-    {
-        return static_cast<T *>(duk_to_pointer(ctx, index));
-    }
-
-    /**
-     * Check if value is a pointer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if pointer
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_pointer(ctx, index);
-    }
-
-    /**
-     * Get a pointer, return defaultValue if the value is not a pointer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \param defaultValue the defaultValue
-     * \return the pointer or defaultValue
-     */
-    static inline T *optional(ContextPtr ctx, int index, T *defaultValue)
-    {
-        return is(ctx, index) ? get(ctx, index) : defaultValue;
-    }
-
-    /**
-     * Push a pointer.
-     *
-     * \param ctx the context
-     * \param value the value
-     */
-    static inline void push(ContextPtr ctx, T *value)
-    {
-        duk_push_pointer(ctx, value);
-    }
-
-    /**
-     * Require a pointer, throws a JavaScript exception if not a pointer.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the pointer
-     */
-    static inline T *require(ContextPtr ctx, int index)
-    {
-        return static_cast<T *>(duk_require_pointer(ctx, index));
-    }
-};
-
-/**
- * \class TypeTraits<Function>
- * \brief Push C++ function to the stack.
- *
- * Provides: push.
- *
- * This implementation push a Duktape/C function that is wrapped as C++ for convenience.
- */
-template <>
-class TypeTraits<Function> {
-public:
-    /**
-     * Check if the value at the given index is callable.
-     *
-     * \param ctx the context
-     * \param index the value index
-     * \return true if the value is callable
-     */
-    static bool is(ContextPtr ctx, Index index)
-    {
-        return duk_is_callable(ctx, index);
-    }
-
-    /**
-     * Push the C++ function, it is wrapped as Duktape/C function and allocated on the heap by moving the
-     * std::function.
-     *
-     * \param ctx the context
-     * \param fn the function
-     */
-    static void push(ContextPtr ctx, Function fn)
-    {
-        duk_push_c_function(ctx, fn.function, fn.nargs);
-    }
-};
-
-/**
- * \class TypeTraits<FunctionMap>
- * \brief Put the functions to the object at the top of the stack.
- *
- * Provides: put.
- */
-template <>
-class TypeTraits<FunctionMap> {
-public:
-    /**
-     * Push all functions to the object at the top of the stack.
-     *
-     * \param ctx the context
-     * \param map the map of function
-     */
-    static void put(ContextPtr ctx, const FunctionMap &map)
-    {
-        StackAssert sa(ctx, 0);
-
-        for (const auto &entry : map) {
-            duk_push_c_function(ctx, entry.second.function, entry.second.nargs);
-            duk_put_prop_string(ctx, -2, entry.first.c_str());
-        }
-    }
-};
-
-/**
- * \class TypeTraits<Object>
- * \brief Push empty object to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeTraits<Object> {
-public:
-    /**
-     * Check if value is an object.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if object
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_object(ctx, index);
-    }
-
-    /**
-     * Create an empty object on the stack.
-     *
-     * \param ctx the context
-     */
-    static inline void push(ContextPtr ctx, const Object &)
-    {
-        duk_push_object(ctx);
-    }
-};
-
-/**
- * \class TypeTraits<Array>
- * \brief Push empty array to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeTraits<Array> {
-public:
-    /**
-     * Check if value is a array.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if array
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_array(ctx, index);
-    }
-
-    /**
-     * Create an empty array on the stack.
-     *
-     * \param ctx the context
-     */
-    static inline void push(ContextPtr ctx, const Array &)
-    {
-        duk_push_array(ctx);
-    }
-};
-
-/**
- * \class TypeTraits<Undefined>
- * \brief Push undefined value to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeTraits<Undefined> {
-public:
-    /**
-     * Check if value is undefined.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if undefined
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_undefined(ctx, index);
-    }
-
-    /**
-     * Push undefined value on the stack.
-     *
-     * \param ctx the context
-     */
-    static inline void push(ContextPtr ctx, const Undefined &)
-    {
-        duk_push_undefined(ctx);
-    }
-};
-
-/**
- * \class TypeTraits<Null>
- * \brief Push null value to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeTraits<Null> {
-public:
-    /**
-     * Check if value is null.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return true if null
-     */
-    static inline bool is(ContextPtr ctx, int index)
-    {
-        return duk_is_null(ctx, index);
-    }
-
-    /**
-     * Push null value on the stack.
-     *
-     * \param ctx the context
-     */
-    static inline void push(ContextPtr ctx, const Null &)
-    {
-        duk_push_null(ctx);
-    }
-};
-
-/**
- * \brief Push this binding into the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeTraits<This> {
-public:
-    /**
-     * Push this function into the stack.
-     *
-     * \param ctx the context
-     */
-    static inline void push(ContextPtr ctx, const This &)
-    {
-        duk_push_this(ctx);
-    }
-};
-
-/**
- * \class TypeTraits<Global>
- * \brief Push the global object to the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeTraits<Global> {
-public:
-    /**
-     * Push the global object into the stack.
-     *
-     * \param ctx the context
-     */
-    static inline void push(ContextPtr ctx, const Global &)
-    {
-        duk_push_global_object(ctx);
-    }
-};
-
-/**
- * \brief Push a map of key-value pair as objects.
- *
- * Provides: push, put.
- *
- * This class is convenient for settings constants such as enums, string and such.
- */
-template <typename T>
-class TypeTraits<std::unordered_map<std::string, T>> {
-public:
-    /**
-     * Put all values from the map as properties to the object at the top of the stack.
-     *
-     * \param ctx the context
-     * \param map the values
-     * \note You need an object at the top of the stack before calling this function
-     */
-    static void push(ContextPtr ctx, const std::unordered_map<std::string, T> &map)
-    {
-        StackAssert sa(ctx, 1);
-
-        duk_push_object(ctx);
-        put(ctx, map);
-    }
-
-    /**
-     * Apply the map to the object at the top of the stack.
-     *
-     * \pre top value must be an object
-     * \param ctx the context
-     * \param map the map
-     */
-    static void put(ContextPtr ctx, const std::unordered_map<std::string, T> &map)
-    {
-        assert(type(ctx, -1) == DUK_TYPE_OBJECT);
-
-        StackAssert sa(ctx);
-
-        for (const auto &pair : map) {
-            TypeTraits<T>::push(ctx, pair.second);
-            duk_put_prop_string(ctx, -2, pair.first.c_str());
-        }
-    }
-};
-
-/**
- * \brief Push or get vectors as JavaScript arrays.
- *
- * Provides: get, push, put.
- */
-template <typename T>
-class TypeTraits<std::vector<T>> {
-public:
-    /**
-     * Get an array from the stack.
-     *
-     * \param ctx the context
-     * \param index the array index
-     * \return the array or empty array if the value is not an array
-     */
-    static std::vector<T> get(ContextPtr ctx, int index)
-    {
-        StackAssert sa(ctx, 0);
-
-        std::vector<T> result;
-
-        if (!duk_is_array(ctx, -1))
-            return result;
-
-        int total = duk_get_length(ctx, index);
-
-        for (int i = 0; i < total; ++i)
-            result.push_back(getProperty<T>(ctx, index, i));
-
-        return result;
-    }
-
-    /**
-     * Create an array with the specified values.
-     *
-     * \param ctx the context
-     * \param array the values
-     */
-    static void push(ContextPtr ctx, const std::vector<T> &array)
-    {
-        StackAssert sa(ctx, 1);
-
-        duk_push_array(ctx);
-        put(ctx, array);
-    }
-
-    /**
-     * Apply the array to the object at the top of the stack.
-     *
-     * \pre top value must be an object
-     * \param ctx the context
-     * \param array the array
-     */
-    static void put(ContextPtr ctx, const std::vector<T> &array)
-    {
-        assert(type(ctx, -1) == DUK_TYPE_OBJECT);
-
-        StackAssert sa(ctx);
-
-        unsigned i = 0;
-        for (const auto &v : array) {
-            TypeTraits<T>::push(ctx, v);
-            duk_put_prop_index(ctx, -2, i++);
-        }
-    }
-};
-
-/**
- * \brief Implementation of managed std::shared_ptr<T>.
- *
- * This specialization requires T to be @ref js-concept-class.
- */
-template <typename T>
-class TypeTraits<std::shared_ptr<T>> {
-private:
-    static void apply(ContextPtr ctx, std::shared_ptr<T> value)
-    {
-        StackAssert sa(ctx, 0);
-
-        duk_push_pointer(ctx, new std::shared_ptr<Bindable>(std::move(value)));
-        duk_put_prop_string(ctx, -2, "\xff""\xff""js-shared-ptr");
-        duk_push_c_function(ctx, [] (duk_context *ctx) -> Ret {
-            duk_get_prop_string(ctx, 0, "\xff""\xff""js-shared-ptr");
-            delete static_cast<std::shared_ptr<Bindable> *>(duk_to_pointer(ctx, -1));
-            duk_pop(ctx);
-            duk_push_null(ctx);
-            duk_put_prop_string(ctx, 0, "\xff""\xff""js-shared-ptr");
-
-            return 0;
-        }, 1);
-        duk_set_finalizer(ctx, -2);
-    }
-
-public:
-    /**
-     * Construct the shared_ptr as this.
-     *
-     * \param ctx the context
-     * \param value the value
-     */
-    static void construct(ContextPtr ctx, std::shared_ptr<T> value)
-    {
-        static_assert(std::is_base_of<Bindable, T>::value, "T must be base of Bindable");
-
-        StackAssert sa(ctx, 0);
-
-        duk_push_this(ctx);
-        apply(ctx, std::move(value));
-        duk_pop(ctx);
-    }
-
-    /**
-     * Push a managed shared_ptr as object.
-     *
-     * \param ctx the context
-     * \param value the value
-     */
-    static void push(ContextPtr ctx, std::shared_ptr<T> value)
-    {
-        static_assert(std::is_base_of<Bindable, T>::value, "T must be base of Bindable");
-
-        StackAssert sa(ctx, 1);
-
-        duk_push_object(ctx);
-        apply(ctx, std::move(value));
-        TypeTraits<T>::prototype(ctx);
-        duk_set_prototype(ctx, -2);
-    }
-
-    /**
-     * Get a managed std::shared_ptr from the stack.
-     *
-     * \param ctx the context
-     * \param index the object index
-     * \return the pointer or a null if invalid
-     */
-    static std::shared_ptr<T> get(ContextPtr ctx, Index index)
-    {
-        static_assert(std::is_base_of<Bindable, T>::value, "T must be base of Bindable");
-
-        StackAssert sa(ctx);
-
-        auto ptr = getProperty<std::shared_ptr<Bindable> *>(ctx, index, "\xff""\xff""js-shared-ptr");
-
-        return (ptr == nullptr) ? nullptr : std::dynamic_pointer_cast<T>(*ptr);
-    }
-
-    /**
-     * Require a managed shared_ptr from the stack.
-     *
-     * Raise a JavaScript error if the object is not valid.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the pointer
-     */
-    static std::shared_ptr<T> require(ContextPtr ctx, Index index)
-    {
-        static_assert(std::is_base_of<Bindable, T>::value, "T must be base of Bindable");
-
-        auto ptr = get(ctx, index);
-
-        if (!ptr)
-            duk::raise(ctx, DUK_ERR_TYPE_ERROR, "invalid this binding");
-
-        return ptr;
-    }
-};
-
-} // !duk
-
-} // !malikania
-
-#endif // !JS_HPP
--- a/tests/libclient/js-animation/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libclient/js-animation/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -21,8 +21,8 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/client-resources-loader.hpp>
 #include <malikania/elapsed-timer.hpp>
+#include <malikania/js-client-resources-loader.hpp>
 #include <malikania/js-animation.hpp>
 #include <malikania/js-animator.hpp>
 #include <malikania/js-window.hpp>
@@ -36,42 +36,38 @@
 protected:
     ResourcesLocatorDirectory m_locator;
     ClientResourcesLoader m_loader;
-
-    duk::Context m_ctx;
+    UniqueContext m_ctx;
 
 public:
     TestAnimation()
         : m_locator(SOURCE_DIRECTORY "/resources")
         , m_loader(m_locator)
     {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
-
-        loadMalikaniaAnimation(m_ctx);
-        loadMalikaniaAnimator(m_ctx);
-        loadMalikaniaWindow(m_ctx);
-
-        /* Store the loader */
-        duk::putGlobal(m_ctx, "\xff""\xff""loader", &m_loader);
+        duk_push_object(m_ctx);
+        duk_put_global_string(m_ctx, "Malikania");
+        dukx_load_animation(m_ctx);
+        dukx_load_animator(m_ctx);
+        dukx_load_window(m_ctx);
+        dukx_put_client_loader(m_ctx, &m_loader);
     }
 };
 
 TEST_F(TestAnimation, basic)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "w = new Malikania.Window();"
             "a = new Malikania.Animation('animations/margins.json');"
             "d = new Malikania.Animator(a);"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
         ElapsedTimer timer;
 
         while (timer.elapsed() < 8000) {
-            auto ret = duk::pevalString(m_ctx,
+            auto ret = duk_peval_string(m_ctx,
                 "w.setDrawingColor('lightskyblue');"
                 "w.clear();"
                 "d.draw(w, { x: 320 - 16, y: 240 - 16 });"
@@ -79,9 +75,8 @@
                 "w.present();"
             );
 
-            if (ret != 0) {
-                throw duk::exception(m_ctx, -1);
-            }
+            if (ret != 0)
+                throw dukx_exception(m_ctx, -1);
         }
 
         std::this_thread::sleep_for(3s);
--- a/tests/libclient/js-color/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libclient/js-color/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -24,14 +24,23 @@
 
 class TestColor : public testing::Test {
 protected:
-    duk::Context m_ctx;
+    UniqueContext m_ctx;
 
 public:
     TestColor()
     {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
+        duk_push_object(m_ctx);
+        duk_put_global_string(m_ctx, "Malikania");
+        dukx_load_color(m_ctx);
+    }
 
-        loadMalikaniaColor(m_ctx);
+    int component(const char *name)
+    {
+        duk_get_global_string(m_ctx, name);
+        auto value = duk_require_int(m_ctx, -1);
+        duk_pop(m_ctx);
+
+        return value;
     }
 };
 
@@ -43,7 +52,7 @@
 TEST_F(TestColor, ConstructorNoArgs)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "c = Malikania.Color();"
             "r = c.red;"
             "g = c.green;"
@@ -51,14 +60,13 @@
             "a = c.alpha;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "a"));
+        ASSERT_EQ(0, component("r"));
+        ASSERT_EQ(0, component("g"));
+        ASSERT_EQ(0, component("b"));
+        ASSERT_EQ(255, component("a"));
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -67,7 +75,7 @@
 TEST_F(TestColor, ConstructorString)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "c = Malikania.Color('white');"
             "r = c.red;"
             "g = c.green;"
@@ -75,14 +83,13 @@
             "a = c.alpha;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "a"));
+        ASSERT_EQ(255, component("r"));
+        ASSERT_EQ(255, component("g"));
+        ASSERT_EQ(255, component("b"));
+        ASSERT_EQ(255, component("a"));
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -91,7 +98,7 @@
 TEST_F(TestColor, ConstructorStringRgb)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "c = Malikania.Color('#0000ff');"
             "r = c.red;"
             "g = c.green;"
@@ -99,14 +106,13 @@
             "a = c.alpha;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "a"));
+        ASSERT_EQ(0, component("r"));
+        ASSERT_EQ(0, component("g"));
+        ASSERT_EQ(255, component("b"));
+        ASSERT_EQ(255, component("a"));
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -115,7 +121,7 @@
 TEST_F(TestColor, Constructor3Args)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "c = Malikania.Color(10, 20, 30);"
             "r = c.red;"
             "g = c.green;"
@@ -123,14 +129,13 @@
             "a = c.alpha;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "a"));
+        ASSERT_EQ(10, component("r"));
+        ASSERT_EQ(20, component("g"));
+        ASSERT_EQ(30, component("b"));
+        ASSERT_EQ(255, component("a"));
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -139,7 +144,7 @@
 TEST_F(TestColor, Constructor4Args)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "c = Malikania.Color(10, 20, 30, 40);"
             "r = c.red;"
             "g = c.green;"
@@ -147,14 +152,13 @@
             "a = c.alpha;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(40, duk::getGlobal<int>(m_ctx, "a"));
+        ASSERT_EQ(10, component("r"));
+        ASSERT_EQ(20, component("g"));
+        ASSERT_EQ(30, component("b"));
+        ASSERT_EQ(40, component("a"));
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -163,7 +167,7 @@
 TEST_F(TestColor, ConstructorObjectNoAlpha)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "c = Malikania.Color({ red: 10, green: 20, blue: 30 });"
             "r = c.red;"
             "g = c.green;"
@@ -171,14 +175,13 @@
             "a = c.alpha;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "a"));
+        ASSERT_EQ(10, component("r"));
+        ASSERT_EQ(20, component("g"));
+        ASSERT_EQ(30, component("b"));
+        ASSERT_EQ(255, component("a"));
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -187,7 +190,7 @@
 TEST_F(TestColor, ConstructorObjectAlpha)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "c = Malikania.Color({ red: 10, green: 20, blue: 30, alpha: 40 });"
             "r = c.red;"
             "g = c.green;"
@@ -195,14 +198,13 @@
             "a = c.alpha;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(40, duk::getGlobal<int>(m_ctx, "a"));
+        ASSERT_EQ(10, component("r"));
+        ASSERT_EQ(20, component("g"));
+        ASSERT_EQ(30, component("b"));
+        ASSERT_EQ(40, component("a"));
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -214,7 +216,7 @@
      * Just one test, function parse the same way, only 'this' or a new object is returned.
      */
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "c = new Malikania.Color({ red: 10, green: 20, blue: 30, alpha: 40 });"
             "r = c.red;"
             "g = c.green;"
@@ -222,14 +224,13 @@
             "a = c.alpha;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(40, duk::getGlobal<int>(m_ctx, "a"));
+        ASSERT_EQ(10, component("r"));
+        ASSERT_EQ(20, component("g"));
+        ASSERT_EQ(30, component("b"));
+        ASSERT_EQ(40, component("a"));
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -243,7 +244,7 @@
 TEST_F(TestColor, InvalidConstructorArg1)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Color(null);"
             "} catch (e) {"
@@ -252,12 +253,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("TypeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -266,7 +270,7 @@
 TEST_F(TestColor, InvalidConstructorArg2)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Color(10, null, 30);"
             "} catch (e) {"
@@ -275,12 +279,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("TypeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -289,7 +296,7 @@
 TEST_F(TestColor, InvalidConstructorRange1)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Color(-1, 20, 30);"
             "} catch (e) {"
@@ -298,12 +305,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -312,7 +322,7 @@
 TEST_F(TestColor, InvalidConstructorRange2)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Color(10, 20, 256);"
             "} catch (e) {"
@@ -321,12 +331,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -335,7 +348,7 @@
 TEST_F(TestColor, InvalidConstructorRange3)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Color(10, 20, 30, 800);"
             "} catch (e) {"
@@ -344,12 +357,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -358,7 +374,7 @@
 TEST_F(TestColor, InvalidConstructorRange4)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Color({ red: -1, green: 20, blue: 30 });"
             "} catch (e) {"
@@ -367,12 +383,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -381,7 +400,7 @@
 TEST_F(TestColor, InvalidConstructorRange5)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Color({ red: 10, green: 20, blue: 30, alpha: 800 });"
             "} catch (e) {"
@@ -390,12 +409,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -404,7 +426,7 @@
 TEST_F(TestColor, InvalidConstructorStringUnknown)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Color('does not exist');"
             "} catch (e) {"
@@ -413,12 +435,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -427,7 +452,7 @@
 TEST_F(TestColor, InvalidConstructorStringRgb)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Color('#ghijkl');"
             "} catch (e) {"
@@ -436,12 +461,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -458,27 +486,39 @@
 TEST_F(TestColor, requireSuccess)
 {
     try {
-        duk::putGlobal(m_ctx, "draw", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Color color = duk::require<Color>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Color color = dukx_require_color(ctx, 0);
 
-            duk::putGlobal(ctx, "r", static_cast<int>(color.red()));
-            duk::putGlobal(ctx, "g", static_cast<int>(color.green()));
-            duk::putGlobal(ctx, "b", static_cast<int>(color.blue()));
-            duk::putGlobal(ctx, "a", static_cast<int>(color.alpha()));
+            duk_push_uint(ctx, color.red());
+            duk_put_global_string(ctx, "r");
+            duk_push_uint(ctx, color.green());
+            duk_put_global_string(ctx, "g");
+            duk_push_uint(ctx, color.blue());
+            duk_put_global_string(ctx, "b");
+            duk_push_uint(ctx, color.alpha());
+            duk_put_global_string(ctx, "a");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "draw");
 
-        auto ret = duk::pevalString(m_ctx, "draw('#ff0000');");
+        auto ret = duk_peval_string(m_ctx, "draw('#ff0000');");
+
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "a"));
+        duk_get_global_string(m_ctx, "r");
+        ASSERT_EQ(255U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "g");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "b");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "a");
+        ASSERT_EQ(255U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -487,13 +527,14 @@
 TEST_F(TestColor, requireFail)
 {
     try {
-        duk::putGlobal(m_ctx, "draw", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            duk::require<Color>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            dukx_require_color(ctx, 0);
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "draw");
 
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  draw('#ghijkl');"
             "} catch (e) {"
@@ -502,12 +543,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -516,13 +560,14 @@
 TEST_F(TestColor, requireFailAlpha)
 {
     try {
-        duk::putGlobal(m_ctx, "draw", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            duk::require<Color>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            dukx_require_color(ctx, 0);
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "draw");
 
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  draw({ red: 10, green: 20, blue: 30, alpha: 800 });"
             "} catch (e) {"
@@ -531,12 +576,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -552,27 +600,39 @@
 TEST_F(TestColor, getNormal)
 {
     try {
-        duk::putGlobal(m_ctx, "draw", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Color color = duk::get<Color>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Color color = dukx_get_color(ctx, 0);
 
-            duk::putGlobal(ctx, "r", static_cast<int>(color.red()));
-            duk::putGlobal(ctx, "g", static_cast<int>(color.green()));
-            duk::putGlobal(ctx, "b", static_cast<int>(color.blue()));
-            duk::putGlobal(ctx, "a", static_cast<int>(color.alpha()));
+            duk_push_uint(ctx, color.red());
+            duk_put_global_string(ctx, "r");
+            duk_push_uint(ctx, color.green());
+            duk_put_global_string(ctx, "g");
+            duk_push_uint(ctx, color.blue());
+            duk_put_global_string(ctx, "b");
+            duk_push_uint(ctx, color.alpha());
+            duk_put_global_string(ctx, "a");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "draw");
 
-        auto ret = duk::pevalString(m_ctx, "draw('#ff0000');");
+        auto ret = duk_peval_string(m_ctx, "draw('#ff0000');");
+
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "a"));
+        duk_get_global_string(m_ctx, "r");
+        ASSERT_EQ(255U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "g");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "b");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "a");
+        ASSERT_EQ(255U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -581,27 +641,39 @@
 TEST_F(TestColor, getAdjustRgb)
 {
     try {
-        duk::putGlobal(m_ctx, "draw", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Color color = duk::get<Color>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Color color = dukx_get_color(ctx, 0);
 
-            duk::putGlobal(ctx, "r", static_cast<int>(color.red()));
-            duk::putGlobal(ctx, "g", static_cast<int>(color.green()));
-            duk::putGlobal(ctx, "b", static_cast<int>(color.blue()));
-            duk::putGlobal(ctx, "a", static_cast<int>(color.alpha()));
+            duk_push_uint(ctx, color.red());
+            duk_put_global_string(ctx, "r");
+            duk_push_uint(ctx, color.green());
+            duk_put_global_string(ctx, "g");
+            duk_push_uint(ctx, color.blue());
+            duk_put_global_string(ctx, "b");
+            duk_push_uint(ctx, color.alpha());
+            duk_put_global_string(ctx, "a");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "draw");
 
-        auto ret = duk::pevalString(m_ctx, "draw('#ghijkl');");
+        auto ret = duk_peval_string(m_ctx, "draw('#ghijkl');");
+
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "a"));
+        duk_get_global_string(m_ctx, "r");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "g");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "b");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "a");
+        ASSERT_EQ(255U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -610,27 +682,39 @@
 TEST_F(TestColor, getAdjustAll)
 {
     try {
-        duk::putGlobal(m_ctx, "draw", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Color color = duk::get<Color>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Color color = dukx_get_color(ctx, 0);
 
-            duk::putGlobal(ctx, "r", static_cast<int>(color.red()));
-            duk::putGlobal(ctx, "g", static_cast<int>(color.green()));
-            duk::putGlobal(ctx, "b", static_cast<int>(color.blue()));
-            duk::putGlobal(ctx, "a", static_cast<int>(color.alpha()));
+            duk_push_uint(ctx, color.red());
+            duk_put_global_string(ctx, "r");
+            duk_push_uint(ctx, color.green());
+            duk_put_global_string(ctx, "g");
+            duk_push_uint(ctx, color.blue());
+            duk_put_global_string(ctx, "b");
+            duk_push_uint(ctx, color.alpha());
+            duk_put_global_string(ctx, "a");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "draw");
 
-        auto ret = duk::pevalString(m_ctx, "draw({ red: -1, green: 256, blue: 100, alpha: 800 });");
+        auto ret = duk_peval_string(m_ctx, "draw({ red: -1, green: 256, blue: 100, alpha: 800 });");
+
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "a"));
+        duk_get_global_string(m_ctx, "r");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "g");
+        ASSERT_EQ(255U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "b");
+        ASSERT_EQ(100U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "a");
+        ASSERT_EQ(255U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -639,27 +723,39 @@
 TEST_F(TestColor, getSomethingElse)
 {
     try {
-        duk::putGlobal(m_ctx, "draw", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Color color = duk::get<Color>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Color color = dukx_get_color(ctx, 0);
 
-            duk::putGlobal(ctx, "r", static_cast<int>(color.red()));
-            duk::putGlobal(ctx, "g", static_cast<int>(color.green()));
-            duk::putGlobal(ctx, "b", static_cast<int>(color.blue()));
-            duk::putGlobal(ctx, "a", static_cast<int>(color.alpha()));
+            duk_push_uint(ctx, color.red());
+            duk_put_global_string(ctx, "r");
+            duk_push_uint(ctx, color.green());
+            duk_put_global_string(ctx, "g");
+            duk_push_uint(ctx, color.blue());
+            duk_put_global_string(ctx, "b");
+            duk_push_uint(ctx, color.alpha());
+            duk_put_global_string(ctx, "a");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "draw");
 
-        auto ret = duk::pevalString(m_ctx, "draw(null);");
+        auto ret = duk_peval_string(m_ctx, "draw(null);");
+
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "g"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "b"));
-        ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "a"));
+        duk_get_global_string(m_ctx, "r");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "g");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "b");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "a");
+        ASSERT_EQ(255U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
--- a/tests/libclient/js-font/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libclient/js-font/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -21,7 +21,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/client-resources-loader.hpp>
+#include <malikania/js-client-resources-loader.hpp>
 #include <malikania/js-font.hpp>
 #include <malikania/js-window.hpp>
 #include <malikania/resources-locator.hpp>
@@ -34,28 +34,25 @@
 protected:
     ResourcesLocatorDirectory m_locator;
     ClientResourcesLoader m_loader;
-
-    duk::Context m_ctx;
+    UniqueContext m_ctx;
 
 public:
     TestFont()
         : m_locator(SOURCE_DIRECTORY "/resources")
         , m_loader(m_locator)
     {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
-
-        loadMalikaniaFont(m_ctx);
-        loadMalikaniaWindow(m_ctx);
-
-        /* Store the loader */
-        duk::putGlobal(m_ctx, "\xff""\xff""loader", &m_loader);
+        duk_push_object(m_ctx);
+        duk_put_global_string(m_ctx, "Malikania");
+        dukx_put_client_loader(m_ctx, &m_loader);
+        dukx_load_font(m_ctx);
+        dukx_load_window(m_ctx);
     }
 };
 
 TEST_F(TestFont, basic)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "w = new Malikania.Window();"
             "f = new Malikania.Font('DejaVuSans.ttf', 10);"
             "w.setDrawingColor('lightskyblue');"
@@ -67,9 +64,8 @@
             "w.present();"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
         std::this_thread::sleep_for(3s);
     } catch (const std::exception &ex) {
--- a/tests/libclient/js-image/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libclient/js-image/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -21,7 +21,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/client-resources-loader.hpp>
+#include <malikania/js-client-resources-loader.hpp>
 #include <malikania/js-image.hpp>
 #include <malikania/js-window.hpp>
 #include <malikania/resources-locator.hpp>
@@ -34,39 +34,39 @@
 protected:
     ResourcesLocatorDirectory m_locator;
     ClientResourcesLoader m_loader;
-
-    duk::Context m_ctx;
+    UniqueContext m_ctx;
 
 public:
     TestImage()
         : m_locator(SOURCE_DIRECTORY "/resources")
         , m_loader(m_locator)
     {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
-
-        loadMalikaniaImage(m_ctx);
-        loadMalikaniaWindow(m_ctx);
-
-        /* Store the loader */
-        duk::putGlobal(m_ctx, "\xff""\xff""loader", &m_loader);
+        duk_push_object(m_ctx);
+        duk_put_global_string(m_ctx, "Malikania");
+        dukx_load_image(m_ctx);
+        dukx_load_window(m_ctx);
+        dukx_put_client_loader(m_ctx, &m_loader);
     }
 };
 
 TEST_F(TestImage, size)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "i = new Malikania.Image('images/smiley.png');"
             "w = i.size.width;"
             "h = i.size.height;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(32, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(32, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(32U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(32U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -75,7 +75,7 @@
 TEST_F(TestImage, basic)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "w = new Malikania.Window();"
             "i = new Malikania.Image('images/smiley.png');"
             "w.setDrawingColor('lightskyblue');"
@@ -84,9 +84,8 @@
             "w.present();"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
         std::this_thread::sleep_for(3s);
     } catch (const std::exception &ex) {
@@ -97,7 +96,7 @@
 TEST_F(TestImage, stretch)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "w = new Malikania.Window();"
             "i = new Malikania.Image('images/smiley.png');"
             "w.setDrawingColor('lightskyblue');"
@@ -106,9 +105,8 @@
             "w.present();"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
         std::this_thread::sleep_for(3s);
     } catch (const std::exception &ex) {
--- a/tests/libclient/js-line/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libclient/js-line/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -24,14 +24,14 @@
 
 class TestLine : public testing::Test {
 protected:
-    duk::Context m_ctx;
+    UniqueContext m_ctx;
 
 public:
     TestLine()
     {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
-
-        loadMalikaniaLine(m_ctx);
+        duk_push_object(m_ctx);
+        duk_put_global_string(m_ctx, "Malikania");
+        dukx_load_line(m_ctx);
     }
 };
 
@@ -43,7 +43,7 @@
 TEST_F(TestLine, ConstructorNoArgs)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "r = Malikania.Line();"
             "x1 = r.x1;"
             "y1 = r.y1;"
@@ -51,14 +51,21 @@
             "y2 = r.y2;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x1"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "y1"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x2"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "y2"));
+        duk_get_global_string(m_ctx, "x1");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y1");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "x2");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y2");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -67,7 +74,7 @@
 TEST_F(TestLine, Constructor4Args)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "r = Malikania.Line(10, 20, 30, 40);"
             "x1 = r.x1;"
             "y1 = r.y1;"
@@ -75,14 +82,21 @@
             "y2 = r.y2;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x1"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "y1"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "x2"));
-        ASSERT_EQ(40, duk::getGlobal<int>(m_ctx, "y2"));
+        duk_get_global_string(m_ctx, "x1");
+        ASSERT_EQ(10, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y1");
+        ASSERT_EQ(20, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "x2");
+        ASSERT_EQ(30, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y2");
+        ASSERT_EQ(40, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -91,7 +105,7 @@
 TEST_F(TestLine, ConstructorObject)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "r = Malikania.Line({ x1: 10, y1: 20, x2: 30, y2: 40 });"
             "x1 = r.x1;"
             "y1 = r.y1;"
@@ -99,14 +113,21 @@
             "y2 = r.y2;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x1"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "y1"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "x2"));
-        ASSERT_EQ(40, duk::getGlobal<int>(m_ctx, "y2"));
+        duk_get_global_string(m_ctx, "x1");
+        ASSERT_EQ(10, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y1");
+        ASSERT_EQ(20, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "x2");
+        ASSERT_EQ(30, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y2");
+        ASSERT_EQ(40, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -115,7 +136,7 @@
 TEST_F(TestLine, ConstructorNew)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "r = new Malikania.Line({ x1: 10, y1: 20, x2: 30, y2: 40 });"
             "x1 = r.x1;"
             "y1 = r.y1;"
@@ -123,14 +144,21 @@
             "y2 = r.y2;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x1"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "y1"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "x2"));
-        ASSERT_EQ(40, duk::getGlobal<int>(m_ctx, "y2"));
+        duk_get_global_string(m_ctx, "x1");
+        ASSERT_EQ(10, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y1");
+        ASSERT_EQ(20, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "x2");
+        ASSERT_EQ(30, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y2");
+        ASSERT_EQ(40, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -144,7 +172,7 @@
 TEST_F(TestLine, InvalidConstructorArg1)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Line(null);"
             "} catch (e) {"
@@ -153,12 +181,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("TypeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -172,27 +203,39 @@
 TEST_F(TestLine, requireSuccess)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Line line = duk::require<Line>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Line line = dukx_require_line(ctx, 0);
 
-            duk::putGlobal(ctx, "x1", line.x1());
-            duk::putGlobal(ctx, "y1", line.y1());
-            duk::putGlobal(ctx, "x2", line.x2());
-            duk::putGlobal(ctx, "y2", line.y2());
+            duk_push_int(ctx, line.x1());
+            duk_put_global_string(ctx, "x1");
+            duk_push_int(ctx, line.y1());
+            duk_put_global_string(ctx, "y1");
+            duk_push_int(ctx, line.x2());
+            duk_put_global_string(ctx, "x2");
+            duk_push_int(ctx, line.y2());
+            duk_put_global_string(ctx, "y2");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx, "build({ x1: 50, y1: 80, x2: 100, y2: 200 });");
+        auto ret = duk_peval_string(m_ctx, "build({ x1: 50, y1: 80, x2: 100, y2: 200 });");
+
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(50, duk::getGlobal<int>(m_ctx, "x1"));
-        ASSERT_EQ(80, duk::getGlobal<int>(m_ctx, "y1"));
-        ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "x2"));
-        ASSERT_EQ(200, duk::getGlobal<int>(m_ctx, "y2"));
+        duk_get_global_string(m_ctx, "x1");
+        ASSERT_EQ(50, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y1");
+        ASSERT_EQ(80, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "x2");
+        ASSERT_EQ(100, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y2");
+        ASSERT_EQ(200, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -201,13 +244,14 @@
 TEST_F(TestLine, requireFail)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            duk::require<Line>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            dukx_require_line(ctx, 0);
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  build({});"
             "} catch (e) {"
@@ -216,12 +260,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -235,27 +282,39 @@
 TEST_F(TestLine, getAdjustAll)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Line line = duk::get<Line>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Line line = dukx_get_line(ctx, 0);
 
-            duk::putGlobal(ctx, "x1", line.x1());
-            duk::putGlobal(ctx, "y1", line.y1());
-            duk::putGlobal(ctx, "x2", line.x2());
-            duk::putGlobal(ctx, "y2", line.y2());
+            duk_push_int(ctx, line.x1());
+            duk_put_global_string(ctx, "x1");
+            duk_push_int(ctx, line.y1());
+            duk_put_global_string(ctx, "y1");
+            duk_push_int(ctx, line.x2());
+            duk_put_global_string(ctx, "x2");
+            duk_push_int(ctx, line.y2());
+            duk_put_global_string(ctx, "y2");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx, "build({});");
+        auto ret = duk_peval_string(m_ctx, "build({});");
+
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x1"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "y1"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x2"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "y2"));
+        duk_get_global_string(m_ctx, "x1");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y1");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "x2");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y2");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
--- a/tests/libclient/js-point/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libclient/js-point/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -24,14 +24,14 @@
 
 class TestPoint : public testing::Test {
 protected:
-    duk::Context m_ctx;
+    UniqueContext m_ctx;
 
 public:
     TestPoint()
     {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
-
-        loadMalikaniaPoint(m_ctx);
+        duk_push_object(m_ctx);
+        duk_put_global_string(m_ctx, "Malikania");
+        dukx_load_point(m_ctx);
     }
 };
 
@@ -43,18 +43,21 @@
 TEST_F(TestPoint, ConstructorNoArgs)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "p = Malikania.Point();"
             "x = p.x;"
             "y = p.y;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "y"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -63,18 +66,21 @@
 TEST_F(TestPoint, Constructor2Args)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "p = Malikania.Point(-10, -20);"
             "x = p.x;"
             "y = p.y;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(-10, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(-20, duk::getGlobal<int>(m_ctx, "y"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(-10, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(-20, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -83,18 +89,21 @@
 TEST_F(TestPoint, ConstructorObject)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "p = Malikania.Point({ x: 100, y: 200 });"
             "x = p.x;"
             "y = p.y;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(200, duk::getGlobal<int>(m_ctx, "y"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(100, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(200, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -103,18 +112,21 @@
 TEST_F(TestPoint, ConstructorNew)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "p = new Malikania.Point({ x: 100, y: 200 });"
             "x = p.x;"
             "y = p.y;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(200, duk::getGlobal<int>(m_ctx, "y"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(100, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(200, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -128,7 +140,7 @@
 TEST_F(TestPoint, InvalidConstructorArg1)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Point(null);"
             "} catch (e) {"
@@ -137,12 +149,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("TypeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -156,23 +171,29 @@
 TEST_F(TestPoint, requireSuccess)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Point point = duk::require<Point>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Point point = dukx_require_point(ctx, 0);
 
-            duk::putGlobal(ctx, "x", point.x());
-            duk::putGlobal(ctx, "y", point.y());
+            duk_push_int(ctx, point.x());
+            duk_put_global_string(ctx, "x");
+            duk_push_int(ctx, point.y());
+            duk_put_global_string(ctx, "y");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx, "build({ x: 100, y: 200 });");
+        auto ret = duk_peval_string(m_ctx, "build({ x: 100, y: 200 });");
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(200, duk::getGlobal<int>(m_ctx, "y"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(100, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(200, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -181,13 +202,14 @@
 TEST_F(TestPoint, requireFail)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            duk::require<Point>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            dukx_require_point(ctx, 0);
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  build({});"
             "} catch (e) {"
@@ -196,12 +218,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -215,23 +240,29 @@
 TEST_F(TestPoint, getAdjustAll)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Point point = duk::get<Point>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Point point = dukx_get_point(ctx, 0);
 
-            duk::putGlobal(ctx, "x", point.x());
-            duk::putGlobal(ctx, "y", point.y());
+            duk_push_int(ctx, point.x());
+            duk_put_global_string(ctx, "x");
+            duk_push_int(ctx, point.y());
+            duk_put_global_string(ctx, "y");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx, "build({});");
+        auto ret = duk_peval_string(m_ctx, "build({});");
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "y"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
--- a/tests/libclient/js-rectangle/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libclient/js-rectangle/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -24,14 +24,14 @@
 
 class TestRectangle : public testing::Test {
 protected:
-    duk::Context m_ctx;
+    UniqueContext m_ctx;
 
 public:
     TestRectangle()
     {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
-
-        loadMalikaniaRectangle(m_ctx);
+        duk_push_object(m_ctx);
+        duk_put_global_string(m_ctx, "Malikania");
+        dukx_load_rect(m_ctx);
     }
 };
 
@@ -43,7 +43,7 @@
 TEST_F(TestRectangle, ConstructorNoArgs)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "r = Malikania.Rectangle();"
             "x = r.x;"
             "y = r.y;"
@@ -51,14 +51,21 @@
             "h = r.height;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "y"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -67,7 +74,7 @@
 TEST_F(TestRectangle, Constructor4Args)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "r = Malikania.Rectangle(10, 20, 30, 40);"
             "x = r.x;"
             "y = r.y;"
@@ -75,14 +82,21 @@
             "h = r.height;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "y"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(40, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(10, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(20, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(30U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(40U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -91,7 +105,7 @@
 TEST_F(TestRectangle, ConstructorObject)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "r = Malikania.Rectangle({ x: 10, y: 20, width: 30, height: 40 });"
             "x = r.x;"
             "y = r.y;"
@@ -99,14 +113,21 @@
             "h = r.height;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "y"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(40, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(10, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(20, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(30U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(40U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -115,7 +136,7 @@
 TEST_F(TestRectangle, ConstructorNew)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "r = new Malikania.Rectangle({ x: 10, y: 20, width: 30, height: 40 });"
             "x = r.x;"
             "y = r.y;"
@@ -123,14 +144,21 @@
             "h = r.height;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(20, duk::getGlobal<int>(m_ctx, "y"));
-        ASSERT_EQ(30, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(40, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(10, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(20, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(30U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(40U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -144,7 +172,7 @@
 TEST_F(TestRectangle, InvalidConstructorArg1)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Rectangle(null);"
             "} catch (e) {"
@@ -153,12 +181,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("TypeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -167,7 +198,7 @@
 TEST_F(TestRectangle, InvalidConstructorRange1)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Rectangle(0, 0, -10, -10);"
             "} catch (e) {"
@@ -176,12 +207,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -195,27 +229,39 @@
 TEST_F(TestRectangle, requireSuccess)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Rectangle rect = duk::require<Rectangle>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Rectangle rect = dukx_require_rect(ctx, 0);
 
-            duk::putGlobal(ctx, "x", rect.x());
-            duk::putGlobal(ctx, "y", rect.y());
-            duk::putGlobal(ctx, "w", static_cast<int>(rect.width()));
-            duk::putGlobal(ctx, "h", static_cast<int>(rect.height()));
+            duk_push_int(ctx, rect.x());
+            duk_put_global_string(ctx, "x");
+            duk_push_int(ctx, rect.y());
+            duk_put_global_string(ctx, "y");
+            duk_push_uint(ctx, rect.width());
+            duk_put_global_string(ctx, "w");
+            duk_push_uint(ctx, rect.height());
+            duk_put_global_string(ctx, "h");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx, "build({ x: 50, y: 80, width: 100, height: 200 });");
+        auto ret = duk_peval_string(m_ctx, "build({ x: 50, y: 80, width: 100, height: 200 });");
+
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(50, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(80, duk::getGlobal<int>(m_ctx, "y"));
-        ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(200, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(50, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(80, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(100U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(200U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -224,13 +270,14 @@
 TEST_F(TestRectangle, requireFail)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            duk::require<Rectangle>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            dukx_require_rect(ctx, 0);
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  build({});"
             "} catch (e) {"
@@ -239,12 +286,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -258,27 +308,38 @@
 TEST_F(TestRectangle, getAdjustAll)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Rectangle rect = duk::get<Rectangle>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Rectangle rect = dukx_get_rect(ctx, 0);
 
-            duk::putGlobal(ctx, "x", rect.x());
-            duk::putGlobal(ctx, "y", rect.y());
-            duk::putGlobal(ctx, "w", static_cast<int>(rect.width()));
-            duk::putGlobal(ctx, "h", static_cast<int>(rect.height()));
+            duk_push_int(ctx, rect.x());
+            duk_put_global_string(ctx, "x");
+            duk_push_int(ctx, rect.y());
+            duk_put_global_string(ctx, "y");
+            duk_push_uint(ctx, rect.width());
+            duk_put_global_string(ctx, "w");
+            duk_push_uint(ctx, rect.height());
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx, "build({});");
+        auto ret = duk_peval_string(m_ctx, "build({});");
+
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "y"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "x");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "y");
+        ASSERT_EQ(0, duk_to_int(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
--- a/tests/libclient/js-size/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libclient/js-size/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -24,14 +24,14 @@
 
 class TestSize : public testing::Test {
 protected:
-    duk::Context m_ctx;
+    UniqueContext m_ctx;
 
 public:
     TestSize()
     {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
-
-        loadMalikaniaSize(m_ctx);
+        duk_push_object(m_ctx);
+        duk_put_global_string(m_ctx, "Malikania");
+        dukx_load_size(m_ctx);
     }
 };
 
@@ -43,18 +43,21 @@
 TEST_F(TestSize, ConstructorNoArgs)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "s = Malikania.Size();"
             "w = s.width;"
             "h = s.height;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -63,18 +66,21 @@
 TEST_F(TestSize, Constructor2Args)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "s = Malikania.Size(100, 200);"
             "w = s.width;"
             "h = s.height;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(200, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(100U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(200U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -83,18 +89,21 @@
 TEST_F(TestSize, ConstructorObject)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "s = Malikania.Size({ width: 100, height: 200 });"
             "w = s.width;"
             "h = s.height;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(200, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(100U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(200U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -103,18 +112,21 @@
 TEST_F(TestSize, ConstructorNew)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "s = new Malikania.Size({ width: 100, height: 200 });"
             "w = s.width;"
             "h = s.height;"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(200, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(100U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(200U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -128,7 +140,7 @@
 TEST_F(TestSize, InvalidConstructorArg1)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Size(null);"
             "} catch (e) {"
@@ -137,12 +149,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("TypeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -151,7 +166,7 @@
 TEST_F(TestSize, InvalidConstructorRange1)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Size(-1, 200);"
             "} catch (e) {"
@@ -160,12 +175,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -174,7 +192,7 @@
 TEST_F(TestSize, InvalidConstructorRange2)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Size(100, -1);"
             "} catch (e) {"
@@ -183,12 +201,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -197,7 +218,7 @@
 TEST_F(TestSize, InvalidConstructorRange3)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Size({ width: -1, height: 200 });"
             "} catch (e) {"
@@ -206,12 +227,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -220,7 +244,7 @@
 TEST_F(TestSize, InvalidConstructorRange4)
 {
     try {
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  Malikania.Size({ width: 100, height: -1 });"
             "} catch (e) {"
@@ -229,12 +253,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("RangeError", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -248,23 +275,29 @@
 TEST_F(TestSize, requireSuccess)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Size size = duk::require<Size>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Size size = dukx_require_size(ctx, 0);
 
-            duk::putGlobal(ctx, "w", static_cast<int>(size.width()));
-            duk::putGlobal(ctx, "h", static_cast<int>(size.height()));
+            duk_push_uint(ctx, size.width());
+            duk_put_global_string(ctx, "w");
+            duk_push_uint(ctx, size.height());
+            duk_put_global_string(ctx, "h");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx, "build({ width: 100, height: 200 });");
+        auto ret = duk_peval_string(m_ctx, "build({ width: 100, height: 200 });");
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(200, duk::getGlobal<int>(m_ctx, "h"));
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(100U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(200U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -273,13 +306,14 @@
 TEST_F(TestSize, requireFail)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            duk::require<Size>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            dukx_require_size(ctx, 0);
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx,
+        auto ret = duk_peval_string(m_ctx,
             "try {"
             "  build({});"
             "} catch (e) {"
@@ -288,12 +322,15 @@
             "}"
         );
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
-        ASSERT_TRUE(duk::getGlobal<bool>(m_ctx, "correct"));
+        duk_get_global_string(m_ctx, "name");
+        ASSERT_STREQ("Error", duk_to_string(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "correct");
+        ASSERT_TRUE(duk_to_boolean(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
@@ -307,23 +344,29 @@
 TEST_F(TestSize, getAdjustAll)
 {
     try {
-        duk::putGlobal(m_ctx, "build", duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
-            Size size = duk::get<Size>(ctx, 0);
+        duk_push_c_function(m_ctx, [] (auto ctx) {
+            Size size = dukx_get_size(ctx, 0);
 
-            duk::putGlobal(ctx, "w", static_cast<int>(size.width()));
-            duk::putGlobal(ctx, "h", static_cast<int>(size.height()));
+            duk_push_uint(ctx, size.width());
+            duk_put_global_string(ctx, "w");
+            duk_push_uint(ctx, size.height());
+            duk_put_global_string(ctx, "h");
 
             return 0;
-        }, 1});
+        }, 1);
+        duk_put_global_string(m_ctx, "build");
 
-        auto ret = duk::pevalString(m_ctx, "build({});");
+        auto ret = duk_peval_string(m_ctx, "build({});");
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+        if (ret != 0)
+            throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
-        ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "g"));
+        duk_get_global_string(m_ctx, "w");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+        ASSERT_EQ(0U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
     } catch (const std::exception &ex) {
         FAIL() << ex.what();
     }
--- a/tests/libclient/js-sprite/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libclient/js-sprite/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -21,7 +21,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/client-resources-loader.hpp>
+#include <malikania/js-client-resources-loader.hpp>
 #include <malikania/js-image.hpp>
 #include <malikania/js-sprite.hpp>
 #include <malikania/js-window.hpp>
@@ -33,153 +33,160 @@
 
 class TestSprite : public testing::Test {
 protected:
-    ResourcesLocatorDirectory m_locator;
-    ClientResourcesLoader m_loader;
-
-    duk::Context m_ctx;
+	ResourcesLocatorDirectory m_locator;
+	ClientResourcesLoader m_loader;
+	UniqueContext m_ctx;
 
 public:
-    TestSprite()
-        : m_locator(SOURCE_DIRECTORY "/resources")
-        , m_loader(m_locator)
-    {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
-
-        loadMalikaniaImage(m_ctx);
-        loadMalikaniaSprite(m_ctx);
-        loadMalikaniaWindow(m_ctx);
-
-        /* Store the loader */
-        duk::putGlobal(m_ctx, "\xff""\xff""loader", &m_loader);
-    }
+	TestSprite()
+		: m_locator(SOURCE_DIRECTORY "/resources")
+		, m_loader(m_locator)
+	{
+        duk_push_object(m_ctx);
+        duk_put_global_string(m_ctx, "Malikania");
+        dukx_load_image(m_ctx);
+        dukx_load_sprite(m_ctx);
+        dukx_load_window(m_ctx);
+        dukx_put_client_loader(m_ctx, &m_loader);
+	}
 };
 
 TEST_F(TestSprite, cell)
 {
-    try {
-        auto ret = duk::pevalString(m_ctx,
-            "s = new Malikania.Sprite('sprites/margins.json');"
-            "w = s.cell.width;"
-            "h = s.cell.height;"
-        );
+	try {
+		auto ret = duk_peval_string(m_ctx,
+			"s = new Malikania.Sprite('sprites/margins.json');"
+			"w = s.cell.width;"
+			"h = s.cell.height;"
+		);
+
+		if (ret != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(32, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(32, duk::getGlobal<int>(m_ctx, "h"));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+        duk_get_global_string(m_ctx, "w");
+		ASSERT_EQ(32U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+		ASSERT_EQ(32U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 TEST_F(TestSprite, columns)
 {
-    try {
-        auto ret = duk::pevalString(m_ctx,
-            "s = new Malikania.Sprite('sprites/margins.json');"
-            "n = s.columns;"
-        );
+	try {
+		auto ret = duk_peval_string(m_ctx,
+			"s = new Malikania.Sprite('sprites/margins.json');"
+			"n = s.columns;"
+		);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+		if (ret != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(4, duk::getGlobal<int>(m_ctx, "n"));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+        duk_get_global_string(m_ctx, "n");
+		ASSERT_EQ(4U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 TEST_F(TestSprite, margins)
 {
-    try {
-        auto ret = duk::pevalString(m_ctx,
-            "s = new Malikania.Sprite('sprites/margins.json');"
-            "w = s.margins.width;"
-            "h = s.margins.height;"
-        );
+	try {
+		auto ret = duk_peval_string(m_ctx,
+			"s = new Malikania.Sprite('sprites/margins.json');"
+			"w = s.margins.width;"
+			"h = s.margins.height;"
+		);
+
+		if (ret != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(4, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(6, duk::getGlobal<int>(m_ctx, "h"));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+        duk_get_global_string(m_ctx, "w");
+		ASSERT_EQ(4U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+		ASSERT_EQ(6U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 TEST_F(TestSprite, rows)
 {
-    try {
-        auto ret = duk::pevalString(m_ctx,
-            "s = new Malikania.Sprite('sprites/margins.json');"
-            "n = s.rows;"
-        );
+	try {
+		auto ret = duk_peval_string(m_ctx,
+			"s = new Malikania.Sprite('sprites/margins.json');"
+			"n = s.rows;"
+		);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+		if (ret != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        ASSERT_EQ(3, duk::getGlobal<int>(m_ctx, "n"));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+        duk_get_global_string(m_ctx, "n");
+		ASSERT_EQ(3U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 TEST_F(TestSprite, space)
 {
-    try {
-        auto ret = duk::pevalString(m_ctx,
-            "s = new Malikania.Sprite('sprites/margins.json');"
-            "w = s.space.width;"
-            "h = s.space.height;"
-        );
+	try {
+		auto ret = duk_peval_string(m_ctx,
+			"s = new Malikania.Sprite('sprites/margins.json');"
+			"w = s.space.width;"
+			"h = s.space.height;"
+		);
+
+		if (ret != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
-
-        ASSERT_EQ(2, duk::getGlobal<int>(m_ctx, "w"));
-        ASSERT_EQ(3, duk::getGlobal<int>(m_ctx, "h"));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+        duk_get_global_string(m_ctx, "w");
+		ASSERT_EQ(2U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+        duk_get_global_string(m_ctx, "h");
+		ASSERT_EQ(3U, duk_to_uint(m_ctx, -1));
+        duk_pop(m_ctx);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 TEST_F(TestSprite, basic)
 {
-    try {
-        auto ret = duk::pevalString(m_ctx,
-            "w = new Malikania.Window();"
-            "s = new Malikania.Sprite('sprites/margins.json');"
-            "c = 0;"
-        );
+	try {
+		auto ret = duk_peval_string(m_ctx,
+			"w = new Malikania.Window();"
+			"s = new Malikania.Sprite('sprites/margins.json');"
+			"c = 0;"
+		);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+		if (ret != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        for (unsigned c = 0; c < 12; ++c) {
-            auto ret = duk::pevalString(m_ctx,
-                "w.setDrawingColor('lightskyblue');"
-                "w.clear();"
-                "s.draw(w, c++, { x: 320 - 16, y: 240 - 16 });"
-                "w.present();"
-            );
+		for (unsigned c = 0; c < 12; ++c) {
+			auto ret = duk_peval_string(m_ctx,
+				"w.setDrawingColor('lightskyblue');"
+				"w.clear();"
+				"s.draw(w, c++, { x: 320 - 16, y: 240 - 16 });"
+				"w.present();"
+			);
 
-            if (ret != 0) {
-                throw duk::exception(m_ctx, -1);
-            }
+			if (ret != 0) {
+				throw dukx_exception(m_ctx, -1);
+			}
 
-            std::this_thread::sleep_for(1s);
-        }
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+			std::this_thread::sleep_for(1s);
+		}
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 int main(int argc, char **argv)
--- a/tests/libclient/js-window/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libclient/js-window/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -29,57 +29,55 @@
 
 class TestWindow : public testing::Test {
 protected:
-    duk::Context m_ctx;
+	UniqueContext m_ctx;
 
 public:
-    TestWindow()
-    {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
-
-        loadMalikaniaWindow(m_ctx);
-    }
+	TestWindow()
+	{
+        duk_push_object(m_ctx);
+		duk_put_global_string(m_ctx, "Malikania");
+        dukx_load_window(m_ctx);
+	}
 };
 
 TEST_F(TestWindow, basic)
 {
-    try {
-        auto ret = duk::pevalString(m_ctx,
-            "w = new Malikania.Window();"
-            "w.setDrawingColor('lightskyblue');"
-            "w.clear();"
-            "w.present();"
-        );
+	try {
+		auto ret = duk_peval_string(m_ctx,
+			"w = new Malikania.Window();"
+			"w.setDrawingColor('lightskyblue');"
+			"w.clear();"
+			"w.present();"
+		);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+		if (ret != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        std::this_thread::sleep_for(3s);
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+		std::this_thread::sleep_for(3s);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 TEST_F(TestWindow, rect)
 {
-    try {
-        auto ret = duk::pevalString(m_ctx,
-            "w = new Malikania.Window();"
-            "w.setDrawingColor('lightskyblue');"
-            "w.clear();"
-            "w.setDrawingColor('white');"
-            "w.drawRectangle({ x: 10, y: 10, width: 10, height: 10 });"
-            "w.present();"
-        );
+	try {
+		auto ret = duk_peval_string(m_ctx,
+			"w = new Malikania.Window();"
+			"w.setDrawingColor('lightskyblue');"
+			"w.clear();"
+			"w.setDrawingColor('white');"
+			"w.drawRectangle({ x: 10, y: 10, width: 10, height: 10 });"
+			"w.present();"
+		);
 
-        if (ret != 0) {
-            throw duk::exception(m_ctx, -1);
-        }
+		if (ret != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        std::this_thread::sleep_for(3s);
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+		std::this_thread::sleep_for(3s);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 int main(int argc, char **argv)
--- a/tests/libcommon/js-elapsed-timer/main.cpp	Fri Jul 01 13:32:08 2016 +0200
+++ b/tests/libcommon/js-elapsed-timer/main.cpp	Wed Aug 10 14:30:51 2016 +0200
@@ -33,111 +33,119 @@
 
 class TestElapsedTimer : public testing::Test {
 protected:
-    duk::Context m_ctx;
-
-    TestElapsedTimer()
-    {
-        duk::putGlobal(m_ctx, "Malikania", duk::Object());
+	UniqueContext m_ctx;
 
-        loadJsElapsedTimer(m_ctx);
-    }
+	TestElapsedTimer()
+	{
+        duk_push_object(m_ctx);
+        duk_put_global_string(m_ctx, "Malikania");
+        dukx_load_elapsedtimer(m_ctx);
+	}
 
-    inline void assertRange(int value, int expected) const noexcept
-    {
-        if (value < (expected - margin) || value > (expected + margin))
-            FAIL() << value << " is bigger than [" << (expected - margin) << ", " << (expected + margin) << "]";
-    }
+	inline void assertRange(int value, int expected) const noexcept
+	{
+		if (value < (expected - margin) || value > (expected + margin))
+			FAIL() << value << " is bigger than [" << (expected - margin) << ", " << (expected + margin) << "]";
+	}
 };
 
 TEST_F(TestElapsedTimer, standard)
 {
-    try {
-        if (duk::pevalString(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-            throw duk::exception(m_ctx, -1);
+	try {
+		if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        std::this_thread::sleep_for(300ms);
+		std::this_thread::sleep_for(300ms);
 
-        if (duk::pevalString(m_ctx, "result = timer.elapsed();") != 0)
-            throw duk::exception(m_ctx, -1);
+		if (duk_peval_string(m_ctx, "result = timer.elapsed();") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        assertRange(duk::getGlobal<int>(m_ctx, "result"), 300);
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+        duk_get_global_string(m_ctx, "result");
+		assertRange(duk_to_int(m_ctx, -1), 300);
+        duk_pop(m_ctx);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 TEST_F(TestElapsedTimer, reset)
 {
-    try {
-        if (duk::pevalString(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-            throw duk::exception(m_ctx, -1);
+	try {
+		if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        std::this_thread::sleep_for(300ms);
+		std::this_thread::sleep_for(300ms);
 
-        if (duk::pevalString(m_ctx, "timer.reset(); result = timer.elapsed();") != 0)
-            throw duk::exception(m_ctx, -1);
+		if (duk_peval_string(m_ctx, "timer.reset(); result = timer.elapsed();") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        assertRange(duk::getGlobal<int>(m_ctx, "result"), 0);
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+        duk_get_global_string(m_ctx, "result");
+		assertRange(duk_to_int(m_ctx, -1), 0);
+        duk_pop(m_ctx);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 TEST_F(TestElapsedTimer, pause)
 {
-    try {
-        if (duk::pevalString(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-            throw duk::exception(m_ctx, -1);
+	try {
+		if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        /*
-         * Simulate a pause in the game like this:
-         *
-         * start     pause restart elapsed
-         * |   10ms   |.5ms.| 6ms  |
-         *
-         * Since the game was paused, the 5ms must not be totalized.
-         */
-        std::this_thread::sleep_for(10ms);
+		/*
+		 * Simulate a pause in the game like this:
+		 *
+		 * start     pause restart elapsed
+		 * |   10ms   |.5ms.| 6ms  |
+		 *
+		 * Since the game was paused, the 5ms must not be totalized.
+		 */
+		std::this_thread::sleep_for(10ms);
+
+		if (duk_peval_string(m_ctx, "timer.pause();") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        if (duk::pevalString(m_ctx, "timer.pause();") != 0)
-            throw duk::exception(m_ctx, -1);
+		std::this_thread::sleep_for(5ms);
 
-        std::this_thread::sleep_for(5ms);
+		if (duk_peval_string(m_ctx, "timer.restart();") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        if (duk::pevalString(m_ctx, "timer.restart();") != 0)
-            throw duk::exception(m_ctx, -1);
+		std::this_thread::sleep_for(6ms);
 
-        std::this_thread::sleep_for(6ms);
-
-        if (duk::pevalString(m_ctx, "result = timer.elapsed()") != 0)
-            throw duk::exception(m_ctx, -1);
+		if (duk_peval_string(m_ctx, "result = timer.elapsed()") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        assertRange(duk::getGlobal<int>(m_ctx, "result"), 16);
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+        duk_get_global_string(m_ctx, "result");
+		assertRange(duk_to_int(m_ctx, -1), 16);
+        duk_pop(m_ctx);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 TEST_F(TestElapsedTimer, doublecheck)
 {
-    try {
-        if (duk::pevalString(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-            throw duk::exception(m_ctx, -1);
+	try {
+		if (duk_peval_string(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        std::this_thread::sleep_for(50ms);
+		std::this_thread::sleep_for(50ms);
 
-        if (duk::pevalString(m_ctx, "result = timer.elapsed()") != 0)
-            throw duk::exception(m_ctx, -1);
+		if (duk_peval_string(m_ctx, "result = timer.elapsed()") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        std::this_thread::sleep_for(50ms);
+		std::this_thread::sleep_for(50ms);
 
-        if (duk::pevalString(m_ctx, "result = timer.elapsed()") != 0)
-            throw duk::exception(m_ctx, -1);
+		if (duk_peval_string(m_ctx, "result = timer.elapsed()") != 0)
+			throw dukx_exception(m_ctx, -1);
 
-        assertRange(duk::getGlobal<int>(m_ctx, "result"), 100);
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+        duk_get_global_string(m_ctx, "result");
+		assertRange(duk_to_int(m_ctx, -1), 100);
+        duk_pop(m_ctx);
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
 }
 
 int main(int argc, char **argv)