changeset 27:0a1adf7dcca0

Common: update libjs and adapt code
author David Demelier <markand@malikania.fr>
date Tue, 12 Apr 2016 13:53:11 +0200
parents 56cc058200b5
children 80736513d699
files client/main.cpp examples/01-bouncing/client.js libclient/CMakeLists.txt libclient/malikania/animation.h libclient/malikania/animator.h libclient/malikania/client.cpp libclient/malikania/client.h libclient/malikania/font.h libclient/malikania/image.h libclient/malikania/js-animation.cpp libclient/malikania/js-animation.h libclient/malikania/js-animator.cpp libclient/malikania/js-animator.h libclient/malikania/js-client-target.cpp libclient/malikania/js-client-target.h libclient/malikania/js-client.cpp libclient/malikania/js-client.h libclient/malikania/js-font.cpp libclient/malikania/js-font.h libclient/malikania/js-image.cpp libclient/malikania/js-image.h libclient/malikania/js-sprite.cpp libclient/malikania/js-window.cpp libclient/malikania/js-window.h libclient/malikania/sprite.h libclient/malikania/window.h libcommon/malikania/elapsed-timer.h libcommon/malikania/js-elapsed-timer.cpp libcommon/malikania/js.h 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 40 files changed, 1533 insertions(+), 676 deletions(-) [+]
line wrap: on
line diff
--- a/client/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/client/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -25,6 +25,8 @@
 
 #include <malikania/js-animation.h>
 #include <malikania/js-animator.h>
+#include <malikania/js-client.h>
+#include <malikania/js-client-target.h>
 #include <malikania/js-color.h>
 #include <malikania/js-font.h>
 #include <malikania/js-image.h>
@@ -64,16 +66,18 @@
 	loadMalikaniaSize(ctx);
 	loadMalikaniaSprite(ctx);
 	loadMalikaniaWindow(ctx);
+	loadMalikaniaClient(ctx);
+	loadMalikaniaClientTarget(ctx);
 
 	return ctx;
 }
 
-void start(duk::Context &ctx)
+void start(duk::Context &ctx, std::shared_ptr<Client> client)
 {
 	duk::getGlobal<void>(ctx, "start");
 
 	if (duk::is<duk::Function>(ctx, -1)) {
-		duk::getGlobal<void>(ctx, "\xff""\xff""window");
+		duk::push(ctx, std::move(client));
 		duk::pcall(ctx, 1);
 		duk::pop(ctx);
 	} else {
@@ -81,44 +85,43 @@
 	}
 }
 
-void update(duk::Context &ctx)
+void update(duk::Context &ctx, std::shared_ptr<Client> client)
 {
 	duk::getGlobal<void>(ctx, "update");
 
 	if (duk::is<duk::Function>(ctx, -1)) {
-		duk::pcall(ctx, 0);
+		duk::push(ctx, std::move(client));
+		duk::pcall(ctx, 1);
 		duk::pop(ctx);
 	} else {
 		duk::pop(ctx);
+		client->update();
 	}
 }
 
-void draw(duk::Context &ctx)
+void draw(duk::Context &ctx, std::shared_ptr<Client> client)
 {
 	duk::getGlobal<void>(ctx, "draw");
 
 	if (duk::is<duk::Function>(ctx, -1)) {
-		duk::getGlobal<void>(ctx, "\xff""\xff""window");
+		duk::push(ctx, std::move(client));
 		duk::pcall(ctx, 1);
 		duk::pop(ctx);
 	} else {
 		duk::pop(ctx);
+		client->draw();
 	}
 }
 
 int run(duk::Context &ctx)
 {
-	bool running = true;
+	auto running = true;
+	auto client = std::make_shared<Client>();
 
-	/* js-window use duk::Pointer at the moment so store it from there temporarily */
-	duk::putGlobal(ctx, "\xff""\xff""window", duk::Pointer<Window>{new Window});
-
-	Window *window = duk::getGlobal<duk::Pointer<Window>>(ctx, "\xff""\xff""window");
-
-	window->setOnQuit([&] () {
+	client->setOnQuit([&] () {
 		running = false;
 	});
-	window->setOnKeyDown([&] (unsigned key) {
+	client->setOnKeyDown([&] (unsigned key) {
 		duk::getGlobal<void>(ctx, "keyDown");
 
 		if (duk::is<duk::Function>(ctx, -1)) {
@@ -129,7 +132,7 @@
 			duk::pop(ctx);
 		}
 	});
-	window->setOnKeyDown([&] (unsigned key) {
+	client->setOnKeyDown([&] (unsigned key) {
 		duk::getGlobal<void>(ctx, "keyUp");
 
 		if (duk::is<duk::Function>(ctx, -1)) {
@@ -141,13 +144,13 @@
 		}
 	});
 
-	start(ctx);
+	start(ctx, client);
 
 	while (running) {
-		window->poll();
+		client->poll();
 
-		update(ctx);
-		draw(ctx);
+		update(ctx, client);
+		draw(ctx, client);
 
 		// TODO: remove this with an appropriate FPS calculation.
 		std::this_thread::sleep_for(std::chrono::milliseconds(50));
@@ -165,10 +168,10 @@
 	ResourcesLocatorDirectory locator(directory);
 	ClientResourcesLoader loader(locator);
 
-	duk::putGlobal(ctx, "\xff""\xff""loader", duk::RawPointer<ClientResourcesLoader>{&loader});
+	duk::putGlobal(ctx, "\xff""\xff""loader", &loader);
 
 	if (duk::pevalFile(ctx, path) != 0) {
-		duk::ErrorInfo info = duk::error(ctx, -1);
+		duk::Exception info = duk::exception(ctx, -1);
 
 		std::cerr << info.fileName << ":" << info.lineNumber << ": " << info.stack << std::endl;
 
--- a/examples/01-bouncing/client.js	Fri Apr 08 14:16:47 2016 +0200
+++ b/examples/01-bouncing/client.js	Tue Apr 12 13:53:11 2016 +0200
@@ -38,4 +38,4 @@
 	window.setDrawingColor('white');
 	window.drawText('Malikania', font, { x: x, y: y });
 	window.present();
-}
\ No newline at end of file
+}
--- a/libclient/CMakeLists.txt	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/CMakeLists.txt	Tue Apr 12 13:53:11 2016 +0200
@@ -20,12 +20,15 @@
 	HEADERS
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/animation.h
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/animator.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/client.h
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-resources-loader.h
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/color.h
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/font.h
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/image.h
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-animation.h
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-animator.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-client-target.h
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-color.h
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-font.h
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-image.h
@@ -49,12 +52,15 @@
 set(
 	SOURCES
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/animator.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/client.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-resources-loader.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/color.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/font.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/image.cpp
 	${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-target.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-color.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-font.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/js-image.cpp
--- a/libclient/malikania/animation.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/animation.h	Tue Apr 12 13:53:11 2016 +0200
@@ -29,6 +29,7 @@
 #include <memory>
 #include <vector>
 
+#include "js.h"
 #include "sprite.h"
 
 namespace malikania {
@@ -86,7 +87,7 @@
  *
  * @see Animator
  */
-class Animation {
+class Animation : public duk::Bindable {
 private:
 	Sprite m_sprite;
 	AnimationFrames m_frames;
--- a/libclient/malikania/animator.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/animator.h	Tue Apr 12 13:53:11 2016 +0200
@@ -24,7 +24,8 @@
  * @brief Draw animations.
  */
 
-#include <malikania/elapsed-timer.h>
+#include "elapsed-timer.h"
+#include "js.h"
 
 namespace malikania {
 
@@ -38,7 +39,7 @@
  *
  * The animator contains an animation and a state.
  */
-class Animator {
+class Animator : public duk::Bindable {
 private:
 	Animation &m_animation;
 	ElapsedTimer m_timer;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -0,0 +1,57 @@
+#include "client.h"
+#include "window.h"
+
+namespace malikania {
+
+Client::Client()
+	: m_loading(std::make_shared<Loading>())
+	, m_target(m_loading)
+{
+}
+
+void Client::setTarget(std::shared_ptr<Target> target)
+{
+	m_targetNext = std::move(target);
+}
+
+void Client::update()
+{
+	if (m_targetNext) {
+		m_target->unload(*this);
+		m_target = std::move(m_targetNext);
+		m_target->load(*this);
+	}
+
+	m_target->update(*this);
+}
+
+void Client::draw()
+{
+	m_target->draw(*this);
+}
+
+void Client::Target::load(Client &)
+{
+}
+
+void Client::Target::update(Client &)
+{
+}
+
+void Client::Target::draw(Client &)
+{
+}
+
+void Client::Target::unload(Client &)
+{
+}
+
+void Client::Loading::update(Client &)
+{
+}
+
+void Client::Loading::draw(Client &)
+{
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client.h	Tue Apr 12 13:53:11 2016 +0200
@@ -0,0 +1,54 @@
+#ifndef MALIKANIA_CLIENT_H
+#define MALIKANIA_CLIENT_H
+
+#include <memory>
+
+#include "window.h"
+
+namespace malikania {
+
+class Client : public Window {
+public:
+	class Target;
+	class Loading;
+
+private:
+	std::shared_ptr<Loading> m_loading;
+	std::shared_ptr<Target> m_target;
+	std::shared_ptr<Target> m_targetNext;
+
+public:
+	Client();
+
+	void setTarget(std::shared_ptr<Target> target);
+
+	void update();
+
+	void draw();
+};
+
+class Client::Target : public duk::Bindable {
+public:
+	Target() = default;
+
+	virtual ~Target() = default;
+
+	virtual void load(Client &client);
+
+	virtual void update(Client &client);
+
+	virtual void draw(Client &client);
+
+	virtual void unload(Client &client);
+};
+
+class Client::Loading : public Client::Target {
+public:
+	virtual void update(Client &client);
+
+	virtual void draw(Client &client);
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_CLIENT_H
--- a/libclient/malikania/font.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/font.h	Tue Apr 12 13:53:11 2016 +0200
@@ -27,6 +27,7 @@
 #include <memory>
 #include <string>
 
+#include "js.h"
 #include "size.h"
 
 namespace malikania {
@@ -35,7 +36,7 @@
  * @class Font
  * @brief Font object.
  */
-class Font {
+class Font : public duk::Bindable {
 private:
 	class Backend;
 
--- a/libclient/malikania/image.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/image.h	Tue Apr 12 13:53:11 2016 +0200
@@ -27,6 +27,7 @@
 #include <memory>
 #include <string>
 
+#include "js.h"
 #include "point.h"
 #include "rectangle.h"
 #include "size.h"
@@ -39,7 +40,7 @@
  * @class Image
  * @brief Image object.
  */
-class Image {
+class Image : public duk::Bindable {
 private:
 	class Backend;
 
--- a/libclient/malikania/js-animation.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-animation.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -32,10 +32,10 @@
 	}
 
 	try {
-		auto loader = duk::getGlobal<duk::RawPointer<ClientResourcesLoader>>(ctx, "\xff""\xff""loader");
+		auto loader = duk::getGlobal<ClientResourcesLoader *>(ctx, "\xff""\xff""loader");
 		auto animation = loader->loadAnimation(duk::require<std::string>(ctx, 0));
 
-		duk::construct(ctx, duk::Pointer<Animation>{new Animation(std::move(animation))});
+		duk::construct(ctx, std::make_shared<Animation>(std::move(animation)));
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
--- a/libclient/malikania/js-animation.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-animation.h	Tue Apr 12 13:53:11 2016 +0200
@@ -24,24 +24,6 @@
 
 namespace malikania {
 
-namespace duk {
-
-template <>
-class TypeTraits<Animation> {
-public:
-	static std::string name()
-	{
-		return "\xff""\xff""Animation";
-	}
-
-	static std::vector<std::string> inherits()
-	{
-		return {};
-	}
-};
-
-} // !duk
-
 void loadMalikaniaAnimation(duk::ContextPtr ctx);
 
 } // !malikania
--- a/libclient/malikania/js-animator.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-animator.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -31,7 +31,7 @@
 		duk::raise(ctx, DUK_ERR_ERROR, "animator must be new-constructed");
 	}
 
-	duk::construct(ctx, duk::Pointer<Animator>{new Animator(*duk::get<duk::Pointer<Animation>>(ctx, 0))});
+	duk::construct(ctx, std::make_shared<Animator>(*duk::require<std::shared_ptr<Animation>>(ctx, 0)));
 
 	/* Be sure animation get not collected before */
 	duk::push(ctx, duk::This());
@@ -44,8 +44,8 @@
 duk::Ret draw(duk::ContextPtr ctx)
 {
 	try {
-		auto self = duk::self<duk::Pointer<Animator>>(ctx);
-		auto window = duk::get<duk::Pointer<Window>>(ctx, 0);
+		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);
@@ -58,7 +58,7 @@
 
 duk::Ret update(duk::ContextPtr ctx)
 {
-	duk::self<duk::Pointer<Animator>>(ctx)->update();
+	duk::self<std::shared_ptr<Animator>>(ctx)->update();
 
 	return 0;
 }
@@ -77,7 +77,7 @@
 	duk::getGlobal<void>(ctx, "Malikania");
 	duk::push(ctx, duk::Function{constructor, 1});
 	duk::push(ctx, duk::Object());
-	duk::push(ctx, methods);
+	duk::put(ctx, methods);
 	duk::putProperty(ctx, -2, "prototype");
 	duk::putProperty(ctx, -2, "Animator");
 	duk::pop(ctx);
--- a/libclient/malikania/js-animator.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-animator.h	Tue Apr 12 13:53:11 2016 +0200
@@ -24,24 +24,6 @@
 
 namespace malikania {
 
-namespace duk {
-
-template <>
-class TypeTraits<Animator> {
-public:
-	static std::string name()
-	{
-		return "\xff""\xff""Animator";
-	}
-
-	static std::vector<std::string> inherits()
-	{
-		return {};
-	}
-};
-
-} // !duk
-
 void loadMalikaniaAnimator(duk::ContextPtr ctx);
 
 } // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/js-client-target.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -0,0 +1,40 @@
+#include "js-client-target.h"
+
+namespace malikania {
+
+class JsTarget : public Client::Target {
+public:
+
+};
+
+namespace {
+
+duk::Ret constructor(duk::ContextPtr ctx)
+{
+
+
+	return 0;
+}
+
+duk::Ret draw(duk::ContextPtr ctx)
+{
+	//duk::self<std::shared_ptr<Client::Target>>(ctx)->draw();
+
+	return 0;
+}
+
+} // !namespace
+
+void loadMalikaniaClientTarget(duk::ContextPtr ctx)
+{
+	duk::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);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/js-client-target.h	Tue Apr 12 13:53:11 2016 +0200
@@ -0,0 +1,13 @@
+#ifndef MALIKANIA_JS_CLIENT_TARGET_H
+#define MALIKANIA_JS_CLIENT_TARGET_H
+
+#include "client.h"
+#include "js.h"
+
+namespace malikania {
+
+void loadMalikaniaClientTarget(duk::ContextPtr ctx);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_CLIENT_TARGET_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/js-client.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -0,0 +1,64 @@
+#include "js-client.h"
+#include "js-client-target.h"
+#include "js-window.h"
+
+namespace malikania {
+
+namespace {
+
+duk::Ret draw(duk::ContextPtr ctx)
+{
+	try {
+		duk::self<std::shared_ptr<Client>>(ctx)->draw();
+	} catch (const std::exception &ex) {
+		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+	}
+
+	return 0;
+}
+
+duk::Ret setTarget(duk::ContextPtr ctx)
+{
+	auto self = duk::self<std::shared_ptr<Client>>(ctx);
+	auto target = duk::get<std::shared_ptr<Client::Target>>(ctx, 0);
+
+	self->setTarget(std::move(target));
+
+	return 0;
+}
+
+duk::Ret update(duk::ContextPtr ctx)
+{
+	try {
+		duk::self<std::shared_ptr<Client>>(ctx)->update();
+	} catch (const std::exception &ex) {
+		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
+	}
+
+	return 0;
+}
+
+const duk::FunctionMap methods{
+	{ "draw",	{ draw, 0 } },
+	{ "setTarget",	{ setTarget, 1 } },
+	{ "update",	{ update, 0 } }
+};
+
+} // !namespace
+
+void loadMalikaniaClient(duk::ContextPtr ctx)
+{
+	duk::StackAssert sa(ctx);
+
+	duk::getGlobal<void>(ctx, "Malikania");
+	duk::push(ctx, duk::Object());
+	duk::push(ctx, duk::Object());
+	duk::TypeTraits<Window>::prototype(ctx);
+	duk::setPrototype(ctx, -2);
+	duk::put(ctx, methods);
+	duk::putProperty(ctx, -2, "prototype");
+	duk::putProperty(ctx, -2, "Client");
+	duk::pop(ctx);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/js-client.h	Tue Apr 12 13:53:11 2016 +0200
@@ -0,0 +1,32 @@
+#ifndef MALIKANIA_JS_CLIENT_H
+#define MALIKANIA_JS_CLIENT_H
+
+#include "client.h"
+#include "js.h"
+
+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);
+
+} // !malikania
+
+#endif // !MALIKANIA_JS_CLIENT_H
--- a/libclient/malikania/js-font.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-font.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -33,7 +33,7 @@
 	}
 
 	try {
-		auto loader = duk::getGlobal<duk::RawPointer<ClientResourcesLoader>>(ctx, "\xff""\xff""loader");
+		auto loader = duk::getGlobal<ClientResourcesLoader *>(ctx, "\xff""\xff""loader");
 		auto id = duk::require<std::string>(ctx, 0);
 		auto size = duk::require<int>(ctx, 1);
 
@@ -41,7 +41,7 @@
 			duk::raise(ctx, DUK_ERR_RANGE_ERROR, "%d must not be negative", size);
 		}
 
-		duk::construct(ctx, duk::Pointer<Font>{new Font(loader->loadFont(id, static_cast<unsigned>(size)))});
+		duk::construct(ctx, std::make_shared<Font>(loader->loadFont(id, static_cast<unsigned>(size))));
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -52,7 +52,7 @@
 duk::Ret clip(duk::ContextPtr ctx)
 {
 	try {
-		duk::push(ctx, duk::self<duk::Pointer<Font>>(ctx)->clip(duk::require<std::string>(ctx, 0)));
+		duk::push(ctx, duk::self<std::shared_ptr<Font>>(ctx)->clip(duk::require<std::string>(ctx, 0)));
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -73,7 +73,7 @@
 	duk::getGlobal<void>(ctx, "Malikania");
 	duk::push(ctx, duk::Function{constructor, 2});
 	duk::push(ctx, duk::Object());
-	duk::push(ctx, methods);
+	duk::put(ctx, methods);
 	duk::putProperty(ctx, -2, "prototype");
 	duk::putProperty(ctx, -2, "Font");
 	duk::pop(ctx);
--- a/libclient/malikania/js-font.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-font.h	Tue Apr 12 13:53:11 2016 +0200
@@ -24,53 +24,6 @@
 
 namespace malikania {
 
-namespace duk {
-
-/**
- * @brief JavaScript binding for Font.
- */
-template <>
-class TypeTraits<Font> {
-public:
-	/**
-	 * Put the Font 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::getGlobal<void>(ctx, "Font");
-		duk::getProperty<void>(ctx, -1, "prototype");
-		duk::remove(ctx, -2);
-		duk::remove(ctx, -2);
-	}
-
-	/**
-	 * Get the object signature.
-	 *
-	 * @return Window signature
-	 */
-	static inline std::string name()
-	{
-		return "\xff""\xff""Font";
-	}
-
-	/**
-	 * Get inheritance list.
-	 *
-	 * @return empty
-	 */
-	static std::vector<std::string> inherits()
-	{
-		return {};
-	}
-};
-
-} // !duk
-
 void loadMalikaniaFont(duk::ContextPtr ctx);
 
 } // !malikania
--- a/libclient/malikania/js-image.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-image.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -30,7 +30,7 @@
 duk::Ret size(duk::ContextPtr ctx)
 {
 	try {
-		duk::push(ctx, duk::self<duk::Pointer<Image>>(ctx)->size());
+		duk::push(ctx, duk::self<std::shared_ptr<Image>>(ctx)->size());
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -41,8 +41,8 @@
 duk::Ret draw(duk::ContextPtr ctx)
 {
 	try {
-		auto self = duk::self<duk::Pointer<Image>>(ctx);
-		auto window = duk::get<duk::Pointer<Window>>(ctx, 0);
+		auto self = duk::self<std::shared_ptr<Image>>(ctx);
+		auto window = duk::get<std::shared_ptr<Window>>(ctx, 0);
 
 		if (duk::top(ctx) == 2) {
 			self->draw(*window, duk::get<Point>(ctx, 1));
@@ -65,10 +65,10 @@
 	}
 
 	try {
-		auto loader = duk::getGlobal<duk::RawPointer<ClientResourcesLoader>>(ctx, "\xff""\xff""loader");
+		auto loader = duk::getGlobal<ClientResourcesLoader *>(ctx, "\xff""\xff""loader");
 		auto image = loader->loadImage(duk::require<std::string>(ctx, 0));
 
-		duk::construct(ctx, duk::Pointer<Image>{new Image(std::move(image))});
+		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});
@@ -94,7 +94,7 @@
 	duk::getGlobal<void>(ctx, "Malikania");
 	duk::push(ctx, duk::Function{constructor, 1});
 	duk::push(ctx, duk::Object());
-	duk::push(ctx, methods);
+	duk::put(ctx, methods);
 	duk::putProperty(ctx, -2, "prototype");
 	duk::putProperty(ctx, -2, "Image");
 	duk::pop(ctx);
--- a/libclient/malikania/js-image.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-image.h	Tue Apr 12 13:53:11 2016 +0200
@@ -24,24 +24,6 @@
 
 namespace malikania {
 
-namespace duk {
-
-template <>
-class TypeTraits<Image> {
-public:
-	static inline std::string name()
-	{
-		return "\xff""\xff""Image";
-	}
-
-	static inline std::vector<std::string> inherits()
-	{
-		return {};
-	}
-};
-
-} // !duk
-
 void loadMalikaniaImage(duk::ContextPtr ctx);
 
 } // !malikania
--- a/libclient/malikania/js-sprite.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-sprite.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -28,35 +28,35 @@
 
 duk::Ret cell(duk::ContextPtr ctx)
 {
-	duk::push(ctx, duk::self<duk::Pointer<Sprite>>(ctx)->cell());
+	duk::push(ctx, duk::self<std::shared_ptr<Sprite>>(ctx)->cell());
 
 	return 1;
 }
 
 duk::Ret columns(duk::ContextPtr ctx)
 {
-	duk::push(ctx, static_cast<int>(duk::self<duk::Pointer<Sprite>>(ctx)->columns()));
+	duk::push(ctx, static_cast<int>(duk::self<std::shared_ptr<Sprite>>(ctx)->columns()));
 
 	return 1;
 }
 
 duk::Ret margins(duk::ContextPtr ctx)
 {
-	duk::push(ctx, duk::self<duk::Pointer<Sprite>>(ctx)->margin());
+	duk::push(ctx, duk::self<std::shared_ptr<Sprite>>(ctx)->margin());
 
 	return 1;
 }
 
 duk::Ret rows(duk::ContextPtr ctx)
 {
-	duk::push(ctx, static_cast<int>(duk::self<duk::Pointer<Sprite>>(ctx)->rows()));
+	duk::push(ctx, static_cast<int>(duk::self<std::shared_ptr<Sprite>>(ctx)->rows()));
 
 	return 1;
 }
 
 duk::Ret space(duk::ContextPtr ctx)
 {
-	duk::push(ctx, duk::self<duk::Pointer<Sprite>>(ctx)->space());
+	duk::push(ctx, duk::self<std::shared_ptr<Sprite>>(ctx)->space());
 
 	return 1;
 }
@@ -68,10 +68,10 @@
 	}
 
 	try {
-		auto loader = duk::getGlobal<duk::RawPointer<ClientResourcesLoader>>(ctx, "\xff""\xff""loader");
+		auto loader = duk::getGlobal<ClientResourcesLoader *>(ctx, "\xff""\xff""loader");
 		auto sprite = loader->loadSprite(duk::require<std::string>(ctx, 0));
 
-		duk::construct(ctx, duk::Pointer<Sprite>{new Sprite(std::move(sprite))});
+		duk::construct(ctx, std::make_shared<Sprite>(std::move(sprite)));
 		duk::push(ctx, duk::This());
 
 		/* Cell */
@@ -110,8 +110,8 @@
 duk::Ret draw(duk::ContextPtr ctx)
 {
 	try {
-		auto self = duk::self<duk::Pointer<Sprite>>(ctx);
-		auto window = duk::get<duk::Pointer<Window>>(ctx, 0);
+		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);
 
@@ -140,7 +140,7 @@
 	duk::getGlobal<void>(ctx, "Malikania");
 	duk::push(ctx, duk::Function{constructor, 1});
 	duk::push(ctx, duk::Object());
-	duk::push(ctx, methods);
+	duk::put(ctx, methods);
 	duk::putProperty(ctx, -2, "prototype");
 	duk::putProperty(ctx, -2, "Sprite");
 	duk::pop(ctx);
--- a/libclient/malikania/js-window.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-window.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -37,7 +37,7 @@
 
 	/* TODO: add parameters */
 	try {
-		duk::construct(ctx, duk::Pointer<Window>{new Window()});
+		duk::construct(ctx, std::make_shared<Window>());
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -48,7 +48,7 @@
 duk::Ret clear(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->clear();
+		duk::self<std::shared_ptr<Window>>(ctx)->clear();
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -59,7 +59,7 @@
 duk::Ret present(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->present();
+		duk::self<std::shared_ptr<Window>>(ctx)->present();
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -70,7 +70,7 @@
 duk::Ret drawingColor(duk::ContextPtr ctx)
 {
 	try {
-		duk::push(ctx, duk::self<duk::Pointer<Window>>(ctx)->drawingColor());
+		duk::push(ctx, duk::self<std::shared_ptr<Window>>(ctx)->drawingColor());
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -81,7 +81,7 @@
 duk::Ret drawLine(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->drawLine(duk::require<Line>(ctx, 0));
+		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());
 	}
@@ -92,7 +92,7 @@
 duk::Ret drawLines(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->drawLines(duk::get<std::vector<Point>>(ctx, 0));
+		duk::self<std::shared_ptr<Window>>(ctx)->drawLines(duk::get<std::vector<Point>>(ctx, 0));
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -103,7 +103,7 @@
 duk::Ret drawPoint(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->drawPoint(duk::require<Point>(ctx, 0));
+		duk::self<std::shared_ptr<Window>>(ctx)->drawPoint(duk::require<Point>(ctx, 0));
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -114,7 +114,7 @@
 duk::Ret drawPoints(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->drawPoints(duk::get<std::vector<Point>>(ctx, 0));
+		duk::self<std::shared_ptr<Window>>(ctx)->drawPoints(duk::get<std::vector<Point>>(ctx, 0));
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -125,7 +125,7 @@
 duk::Ret drawRectangle(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->drawRectangle(duk::require<Rectangle>(ctx, 0));
+		duk::self<std::shared_ptr<Window>>(ctx)->drawRectangle(duk::require<Rectangle>(ctx, 0));
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -136,7 +136,7 @@
 duk::Ret drawRectangles(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->drawRectangles(duk::get<std::vector<Rectangle>>(ctx, 0));
+		duk::self<std::shared_ptr<Window>>(ctx)->drawRectangles(duk::get<std::vector<Rectangle>>(ctx, 0));
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -147,9 +147,9 @@
 duk::Ret drawText(duk::ContextPtr ctx)
 {
 	try {
-		auto self = duk::self<duk::Pointer<Window>>(ctx);
+		auto self = duk::self<std::shared_ptr<Window>>(ctx);
 		auto text = duk::require<std::string>(ctx, 0);
-		auto font = duk::get<duk::Pointer<Font>>(ctx, 1);
+		auto font = duk::get<std::shared_ptr<Font>>(ctx, 1);
 		auto rect = duk::get<Rectangle>(ctx, 2);
 
 		if (!rect.isNull()) {
@@ -167,7 +167,7 @@
 duk::Ret fillRectangle(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->fillRectangle(duk::require<Rectangle>(ctx, 0));
+		duk::self<std::shared_ptr<Window>>(ctx)->fillRectangle(duk::require<Rectangle>(ctx, 0));
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -178,7 +178,7 @@
 duk::Ret fillRectangles(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->fillRectangles(duk::get<std::vector<Rectangle>>(ctx, 0));
+		duk::self<std::shared_ptr<Window>>(ctx)->fillRectangles(duk::get<std::vector<Rectangle>>(ctx, 0));
 	} catch (const std::exception &ex) {
 		duk::raise(ctx, DUK_ERR_ERROR, "%s", ex.what());
 	}
@@ -189,7 +189,7 @@
 duk::Ret setDrawingColor(duk::ContextPtr ctx)
 {
 	try {
-		duk::self<duk::Pointer<Window>>(ctx)->setDrawingColor(duk::require<Color>(ctx, 0));
+		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());
 	}
@@ -222,7 +222,7 @@
 	duk::getGlobal<void>(ctx, "Malikania");
 	duk::push(ctx, duk::Function{constructor});
 	duk::push(ctx, duk::Object());
-	duk::push(ctx, methods);
+	duk::put(ctx, methods);
 	duk::putProperty(ctx, -2, "prototype");
 	duk::putProperty(ctx, -2, "Window");
 	duk::pop(ctx);
--- a/libclient/malikania/js-window.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/js-window.h	Tue Apr 12 13:53:11 2016 +0200
@@ -47,26 +47,6 @@
 		duk::remove(ctx, -2);
 		duk::remove(ctx, -2);
 	}
-
-	/**
-	 * Get the object signature.
-	 *
-	 * @return Window signature
-	 */
-	static inline std::string name()
-	{
-		return "\xff""\xff""Window";
-	}
-
-	/**
-	 * Get inheritance list.
-	 *
-	 * @return empty
-	 */
-	static std::vector<std::string> inherits()
-	{
-		return {};
-	}
 };
 
 } // !duk
--- a/libclient/malikania/sprite.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/sprite.h	Tue Apr 12 13:53:11 2016 +0200
@@ -27,6 +27,7 @@
 #include <malikania/json.h>
 
 #include "image.h"
+#include "js.h"
 
 namespace malikania {
 
@@ -37,7 +38,7 @@
  * @class Sprite
  * @brief A Sprite is an image divided into cells.
  */
-class Sprite {
+class Sprite : public duk::Bindable {
 private:
 	Image m_image;
 	Size m_cell;
--- a/libclient/malikania/window.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libclient/malikania/window.h	Tue Apr 12 13:53:11 2016 +0200
@@ -29,6 +29,8 @@
 #include <vector>
 #include <string>
 
+#include "js.h"
+
 namespace malikania {
 
 class Color;
@@ -40,7 +42,7 @@
 /**
  * @brief Main window class and drawing.
  */
-class Window {
+class Window : public duk::Bindable {
 private:
 	class Backend;
 
--- a/libcommon/malikania/elapsed-timer.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libcommon/malikania/elapsed-timer.h	Tue Apr 12 13:53:11 2016 +0200
@@ -26,6 +26,8 @@
 
 #include <chrono>
 
+#include "js.h"
+
 namespace malikania {
 
 /**
@@ -38,7 +40,7 @@
  * It uses std::chrono::high_resolution_clock for more precision and uses
  * milliseconds only.
  */
-class ElapsedTimer {
+class ElapsedTimer : public duk::Bindable {
 public:
 	using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
 
--- a/libcommon/malikania/js-elapsed-timer.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/libcommon/malikania/js-elapsed-timer.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -21,24 +21,6 @@
 
 namespace malikania {
 
-namespace duk {
-
-template <>
-class TypeTraits<ElapsedTimer> {
-public:
-	static inline std::string name()
-	{
-		return "\xff""\xff""ElapsedTimer";
-	}
-
-	static inline std::vector<std::string> inherits()
-	{
-		return {};
-	}
-};
-
-} // !duk
-
 namespace {
 
 /*
@@ -49,7 +31,7 @@
  */
 duk::Ret pause(duk::ContextPtr ctx)
 {
-	duk::self<duk::Pointer<ElapsedTimer>>(ctx)->pause();
+	duk::self<std::shared_ptr<ElapsedTimer>>(ctx)->pause();
 
 	return 0;
 }
@@ -62,7 +44,7 @@
  */
 duk::Ret reset(duk::ContextPtr ctx)
 {
-	duk::self<duk::Pointer<ElapsedTimer>>(ctx)->reset();
+	duk::self<std::shared_ptr<ElapsedTimer>>(ctx)->reset();
 
 	return 0;
 }
@@ -75,7 +57,7 @@
  */
 duk::Ret restart(duk::ContextPtr ctx)
 {
-	duk::self<duk::Pointer<ElapsedTimer>>(ctx)->restart();
+	duk::self<std::shared_ptr<ElapsedTimer>>(ctx)->restart();
 
 	return 0;
 }
@@ -91,7 +73,7 @@
  */
 duk::Ret elapsed(duk::ContextPtr ctx)
 {
-	duk::push(ctx, (int)duk::self<duk::Pointer<ElapsedTimer>>(ctx)->elapsed());
+	duk::push(ctx, (int)duk::self<std::shared_ptr<ElapsedTimer>>(ctx)->elapsed());
 
 	return 1;
 }
@@ -104,7 +86,7 @@
  */
 duk::Ret constructor(duk::ContextPtr ctx)
 {
-	duk::construct(ctx, duk::Pointer<ElapsedTimer>{new ElapsedTimer});
+	duk::construct(ctx, std::make_shared<ElapsedTimer>());
 
 	return 0;
 }
@@ -125,7 +107,7 @@
 	duk::getGlobal<void>(ctx, "Malikania");
 	duk::push(ctx, duk::Function{constructor, 0});
 	duk::push(ctx, duk::Object{});
-	duk::push(ctx, methods);
+	duk::put(ctx, methods);
 	duk::putProperty(ctx, -2, "prototype");
 	duk::putProperty(ctx, -2, "ElapsedTimer");
 	duk::pop(ctx);
--- a/libcommon/malikania/js.h	Fri Apr 08 14:16:47 2016 +0200
+++ b/libcommon/malikania/js.h	Tue Apr 12 13:53:11 2016 +0200
@@ -29,6 +29,627 @@
  * 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.h** 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.h"
+ *
+ * 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.h"
+ *
+ * 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.h"
+ *
+ * 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.h"
+ *
+ * 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>
@@ -49,11 +670,35 @@
 
 class Context;
 
-using CodePoint = duk_codepoint_t;
+/**
+ * @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;
-using Size = duk_size_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
@@ -110,95 +755,131 @@
 };
 
 /**
+ * @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 Empty class tag for push() function.
+ * @brief Special type for duk::TypeTraits.
  */
 class Object {
 };
 
 /**
  * @class Array
- * @brief Empty class tag for push() function.
+ * @brief Special type for duk::TypeTraits.
  */
 class Array {
 };
 
 /**
  * @class Global
- * @brief Empty class tag to push the global object.
+ * @brief Special type for duk::TypeTraits.
  */
 class Global {
 };
 
 /**
  * @class Undefined
- * @brief Empty class tag to push undefined to the stack.
+ * @brief Special type for duk::TypeTraits.
  */
 class Undefined {
 };
 
 /**
  * @class Null
- * @brief Empty class tag to push null to the stack.
+ * @brief Special type for duk::TypeTraits.
  */
 class Null {
 };
 
 /**
  * @class This
- * @brief Empty class tag to push this binding to the stack.
+ * @brief Special type for duk::TypeTraits.
  */
 class This {
 };
 
 /**
- * @class RawPointer
- * @brief Push a non-managed pointer to Duktape, the pointer will never be deleted.
- * @note For a managed pointer with prototype, see Pointer
- */
-template <typename T>
-class RawPointer {
-public:
-	/**
-	 * The pointer to push.
-	 */
-	T *object;
-};
-
-/**
- * @brief Manage shared_ptr from C++ and JavaScript
- *
- * This class allowed you to push and retrieve shared_ptr from C++ and JavaScript without taking care of ownership
- * and deletion.
- *
- */
-template <typename T>
-class Shared {
-public:
-	/**
-	 * The shared object.
-	 */
-	std::shared_ptr<T> object;
-};
-
-/**
- * @brief Manage pointers from C++ and JavaScript
- *
- * This class allowed you to push and retrieve C++ pointers from C++ and JavaScript. The object will be deleted when
- * the JavaScript garbage collectors collect them so never store a pointer created with this.
- *
- * The only requirement is to have the function `void prototype(Context &ctx)` in your class T.
- */
-template <typename T>
-class Pointer {
-public:
-	/**
-	 * The object.
-	 */
-	T *object{nullptr};
-};
-
-/**
  * @class Function
  * @brief Duktape/C function definition.
  *
@@ -218,23 +899,23 @@
 };
 
 /**
- * Map of functions to set on an object.
+ * @brief Map of functions.
  */
 using FunctionMap = std::unordered_map<std::string, Function>;
 
 /**
- * Map of string to type, ideal for setting constants like enums.
+ * @brief Map of any type.
  */
-template <typename Type>
-using Map = std::unordered_map<std::string, Type>;
+template <typename T>
+using Map = std::unordered_map<std::string, T>;
 
 /**
- * @class ErrorInfo
+ * @class Exception
  * @brief Error description.
  *
  * This class fills the fields got in an Error object.
  */
-class ErrorInfo : public std::exception {
+class Exception : public std::exception {
 public:
 	std::string name;		//!< name of error
 	std::string message;		//!< error message
@@ -254,42 +935,6 @@
 };
 
 /**
- * @class TypeTraits
- * @brief Type information to implement new types in JavaScript's context.
- *
- * This class depending on your needs may have the following functions:
- *
- * - `static void construct(Context &ctx, Type value)`
- * - `static Type get(Context &ctx, int index)`
- * - `static bool is(Context &ctx, int index)`
- * - `static Type optional(Context &ctx, int index, Type defaultValue)`
- * - `static void push(Context &ctx, Type value)`
- * - `static Type require(Context &ctx, int index)`
- *
- * The `construct` function is used in Context::construct to build a new value as this (e.g. constructors).
- *
- * The `get` function is used in Context::get, Context::getProperty, Context::getGlobal to retrieve a value from the
- * stack.
- *
- * The `is` function is used in Context::is to check if the value on the stack is of type `Type`.
- *
- * The `optional` function is used in Context::optional to get a value or a replacement if not applicable.
- *
- * The `push` function is used in Context::push to usually create a new value on the stack but some specializations
- * may not (e.g. FunctionMap).
- *
- * The `require` function is used in Context::require to get a value from the stack or raise a JavaScript exception if
- * not applicable.
- *
- * This class is fully specialized for: `bool`, `const char *`, `double`, `int`, `std::string`.
- *
- * It is also partially specialized for : `Global`, `Object`, `Array`, `Undefined`, `Null`, `std::vector<Type>`.
- */
-template <typename Type>
-class TypeTraits {
-};
-
-/**
  * @class Context
  * @brief RAII based Duktape handler.
  *
@@ -305,7 +950,6 @@
 	Context(const Context &) = delete;
 	Context &operator=(const Context &) = delete;
 
-
 public:
 	/**
 	 * Create default context.
@@ -315,8 +959,10 @@
 	{
 	}
 
+	/**
+	 * Default move constructor.
+	 */
 	Context(Context &&) noexcept = default;
-	Context &operator=(Context &&) noexcept = default;
 
 	/**
 	 * Convert the context to the native Duktape/C type.
@@ -337,35 +983,23 @@
 	{
 		return m_handle.get();
 	}
+
+	/**
+	 * Default move assignment operator.
+	 */
+	Context &operator=(Context &&) noexcept = delete;
 };
 
 /**
- * Get the error object when a JavaScript error has been thrown (e.g. eval failure).
+ * @name Duktape C functions
+ * @brief The following functions are wrappers on top of the Duktape C functions.
  *
- * @param ctx the context
- * @param index the index
- * @return the information
+ * They are as close as possible to the original functions.
  */
-inline ErrorInfo error(ContextPtr ctx, int index)
-{
-	ErrorInfo error;
-
-	index = duk_normalize_index(ctx, index);
 
-	duk_get_prop_string(ctx, index, "name");
-	error.name = duk_to_string(ctx, -1);
-	duk_get_prop_string(ctx, index, "message");
-	error.message = duk_to_string(ctx, -1);
-	duk_get_prop_string(ctx, index, "fileName");
-	error.fileName = duk_to_string(ctx, -1);
-	duk_get_prop_string(ctx, index, "lineNumber");
-	error.lineNumber = duk_to_int(ctx, -1);
-	duk_get_prop_string(ctx, index, "stack");
-	error.stack = duk_to_string(ctx, -1);
-	duk_pop_n(ctx, 5);
-
-	return error;
-}
+/**
+ * @{
+ */
 
 /**
  * Wrapper for [duk_base64_decode](http://duktape.org/api.html#duk_base64_decode).
@@ -383,10 +1017,11 @@
  *
  * @param ctx the context
  * @param index the index
+ * @return the base64 string
  */
-inline void base64Encode(ContextPtr ctx, Index index)
+inline std::string base64Encode(ContextPtr ctx, Index index)
 {
-	duk_base64_encode(ctx, index);
+	return duk_base64_encode(ctx, index);
 }
 
 /**
@@ -430,7 +1065,7 @@
  * @param index the index
  * @param charOffset the offset
  */
-inline CodePoint charCodeAt(ContextPtr ctx, Index index, Size charOffset)
+inline duk_codepoint_t charCodeAt(ContextPtr ctx, Index index, duk_size_t charOffset)
 {
 	return duk_char_code_at(ctx, index, charOffset);
 }
@@ -510,6 +1145,7 @@
 /**
  * Wrapper for [duk_copy](http://duktape.org/api.html#duk_copy).
  *
+ * @param ctx the context
  * @param from the from index
  * @param to the destination
  */
@@ -519,8 +1155,20 @@
 }
 
 /**
+ * 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
  */
@@ -532,6 +1180,7 @@
 /**
  * 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
  */
@@ -543,6 +1192,7 @@
 /**
  * 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
@@ -555,6 +1205,7 @@
 /**
  * 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
@@ -567,6 +1218,7 @@
 /**
  * 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)
@@ -727,10 +1379,11 @@
  *
  * @param ctx the context
  * @param index the index
+ * @return the JSON string
  */
-inline void jsonEncode(ContextPtr ctx, Index index)
+inline std::string jsonEncode(ContextPtr ctx, Index index)
 {
-	duk_json_encode(ctx, index);
+	return duk_json_encode(ctx, index);
 }
 
 /**
@@ -756,6 +1409,29 @@
 }
 
 /**
+ * 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
@@ -801,6 +1477,41 @@
 }
 
 /**
+ * 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
@@ -862,34 +1573,95 @@
  * @param ctx the context
  * @return the stack size
  */
-inline int top(ContextPtr ctx) noexcept
+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) noexcept
+inline int type(ContextPtr ctx, Index index)
 {
 	return duk_get_type(ctx, index);
 }
 
-/*
- * Push / Get / Require / Is / Optional
- * ----------------------------------------------------------
+/**
+ * @}
+ */
+
+/**
+ * @name Extended functions
+ * @brief Extended functions for libjs.
  *
- * The following functions are used to push, get or check values from the stack. They use specialization
- * of TypeTraits class.
+ * The following functions are largely modified or extensions to Duktape.
+ */
+
+/**
+ * @{
  */
 
 /**
- * Push a value into the stack. Calls TypeTraits<T>::push(*this, value);
+ * 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>
@@ -899,8 +1671,21 @@
 }
 
 /**
+ * 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
  */
@@ -913,6 +1698,7 @@
 /**
  * Require a type at the specified index.
  *
+ * @param ctx the context
  * @param index the index
  * @return the value
  */
@@ -927,6 +1713,7 @@
  *
  * 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
  */
@@ -942,6 +1729,7 @@
  *
  * 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
@@ -952,16 +1740,10 @@
 	return TypeTraits<std::decay_t<Type>>::optional(ctx, index, std::forward<Type>(defaultValue));
 }
 
-/*
- * Properties management
- * ----------------------------------------------------------
- *
- * The following functions are used to read or set properties on objects or globals also using TypeTraits.
- */
-
 /**
  * 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
@@ -980,6 +1762,7 @@
 /**
  * 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
@@ -998,6 +1781,7 @@
 /**
  * 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
@@ -1011,6 +1795,7 @@
 /**
  * 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
@@ -1024,6 +1809,7 @@
 /**
  * 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
@@ -1043,6 +1829,7 @@
 /**
  * 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
@@ -1062,6 +1849,7 @@
 /**
  * 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
@@ -1079,6 +1867,7 @@
 /**
  * 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
@@ -1094,30 +1883,9 @@
 }
 
 /**
- * Put the value that is at the top of the stack as property to the object.
- *
- * @param index the object index
- * @param name the property name
- */
-inline void putProperty(ContextPtr ctx, int index, const std::string &name)
-{
-	duk_put_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Put the value that is at the top of the stack to the object as index.
- *
- * @param index the object index
- * @param position the position in the object
- */
-inline void putProperty(ContextPtr ctx, int index, int position)
-{
-	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
  */
@@ -1135,7 +1903,7 @@
  * 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) noexcept
+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());
 }
@@ -1143,6 +1911,7 @@
 /**
  * Set a global variable.
  *
+ * @param ctx the context
  * @param name the name of the global variable
  * @param type the value to set
  */
@@ -1156,6 +1925,7 @@
 /**
  * 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)
@@ -1163,16 +1933,10 @@
 	duk_put_global_string(ctx, name.c_str());
 }
 
-/*
- * Extra functions
- * ----------------------------------------------------------
- *
- * The following functions are implemented for convenience and do not exists in the native Duktape API.
- */
-
 /**
  * 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
@@ -1194,13 +1958,14 @@
 /**
  * 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>::get(ctx, 0))
+inline auto self(ContextPtr ctx) -> decltype(TypeTraits<T>::require(ctx, 0))
 {
 	duk_push_this(ctx);
-	decltype(TypeTraits<T>::get(ctx, 0)) value = TypeTraits<T>::get(ctx, -1);
+	decltype(TypeTraits<T>::require(ctx, 0)) value = TypeTraits<T>::require(ctx, -1);
 	duk_pop(ctx);
 
 	return value;
@@ -1209,6 +1974,7 @@
 /**
  * Throw an ECMAScript exception.
  *
+ * @param ctx the context
  * @param ex the exception
  */
 template <typename Exception>
@@ -1218,47 +1984,13 @@
 }
 
 /**
- * Wrapper for duk_throw.
- *
- * @param ctx the context
- */
-inline void raise(ContextPtr ctx)
-{
-	duk_throw(ctx);
-}
-
-/**
- * Wrapper for 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_new.
- *
- * @param ctx the context
- * @param nargs the number of arguments
- */
-inline void create(ContextPtr ctx, int nargs = 0)
-{
-	duk_new(ctx, nargs);
-}
-
-/**
  * 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
  */
@@ -1269,63 +2001,8 @@
 }
 
 /**
- * Sign the given object with the name from T.
- *
- * This is automatically done for when constructing/pushing object with Shared and Pointer helpers, however you need
- * to manually add it when using inheritance.
+ * @}
  */
-template <typename T>
-inline void sign(ContextPtr ctx, Index index)
-{
-	StackAssert sa(ctx, 0);
-
-	index = duk_normalize_index(ctx, index);
-
-	duk_push_string(ctx, TypeTraits<T>::name().c_str());
-	duk_push_boolean(ctx, true);
-	duk_def_prop(ctx, index < 0 ? index : index, DUK_DEFPROP_HAVE_VALUE);
-
-	/* Do for inherited classes */
-	for (const std::string &parent : TypeTraits<T>::inherits()) {
-		duk_push_string(ctx, parent.c_str());
-		duk_push_boolean(ctx, true);
-		duk_def_prop(ctx, index < 0 ? index : index, DUK_DEFPROP_HAVE_VALUE);
-	}
-}
-
-/**
- * Check if the object at the given index is signed by T or raise TypeError if not.
- *
- * @param ctx the context
- * @param index the index
- * @see sign
- */
-template <typename T>
-inline void checkSignature(ContextPtr ctx, Index index)
-{
-	StackAssert sa(ctx, 0);
-
-	if (!is<Object>(ctx, index) || !getProperty<bool>(ctx, index, TypeTraits<T>::name()))
-		raise(ctx, DUK_ERR_TYPE_ERROR, "invalid this binding");
-}
-
-/**
- * Tells if the object at the specified index is of type T.
- *
- * @param ctx the context
- * @param index the index
- */
-template <typename T>
-inline bool isSigned(ContextPtr ctx, Index index)
-{
-	StackAssert sa(ctx, 0);
-
-	return is<Object>(ctx, index) && getProperty<bool>(ctx, index, TypeTraits<T>::name());
-}
-
-/* ------------------------------------------------------------------
- * Exception handling
- * ------------------------------------------------------------------ */
 
 /**
  * @class Error
@@ -1367,7 +2044,7 @@
 	 * @note the default implementation search for the global variables
 	 * @param ctx the context
 	 */
-	virtual void raise(ContextPtr ctx) const noexcept
+	virtual void raise(ContextPtr ctx) const
 	{
 		duk_error(ctx, m_type, "%s", m_message.c_str());
 	}
@@ -1838,12 +2515,82 @@
 };
 
 /**
+ * @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<RawPointer<T>> {
+class TypeTraits<T *> {
 public:
 	/**
 	 * Get a pointer, return nullptr if not a pointer.
@@ -1877,9 +2624,9 @@
 	 * @param defaultValue the defaultValue
 	 * @return the pointer or defaultValue
 	 */
-	static inline T *optional(ContextPtr ctx, int index, RawPointer<T> defaultValue)
+	static inline T *optional(ContextPtr ctx, int index, T *defaultValue)
 	{
-		return is(ctx, index) ? get(ctx, index) : defaultValue.object;
+		return is(ctx, index) ? get(ctx, index) : defaultValue;
 	}
 
 	/**
@@ -1888,9 +2635,9 @@
 	 * @param ctx the context
 	 * @param value the value
 	 */
-	static inline void push(ContextPtr ctx, const RawPointer<T> &value)
+	static inline void push(ContextPtr ctx, T *value)
 	{
-		duk_push_pointer(ctx, value.object);
+		duk_push_pointer(ctx, value);
 	}
 
 	/**
@@ -1946,7 +2693,7 @@
  * @class TypeTraits<FunctionMap>
  * @brief Put the functions to the object at the top of the stack.
  *
- * Provides: push.
+ * Provides: put.
  */
 template <>
 class TypeTraits<FunctionMap> {
@@ -1957,7 +2704,7 @@
 	 * @param ctx the context
 	 * @param map the map of function
 	 */
-	static inline void push(ContextPtr ctx, const FunctionMap &map)
+	static void put(ContextPtr ctx, const FunctionMap &map)
 	{
 		StackAssert sa(ctx, 0);
 
@@ -2138,7 +2885,7 @@
 /**
  * @brief Push a map of key-value pair as objects.
  *
- * Provides: push.
+ * Provides: push, put.
  *
  * This class is convenient for settings constants such as enums, string and such.
  */
@@ -2157,6 +2904,21 @@
 		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);
@@ -2168,7 +2930,7 @@
 /**
  * @brief Push or get vectors as JavaScript arrays.
  *
- * Provides: get, push.
+ * Provides: get, push, put.
  */
 template <typename T>
 class TypeTraits<std::vector<T>> {
@@ -2208,6 +2970,21 @@
 		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) {
@@ -2218,23 +2995,22 @@
 };
 
 /**
- * @brief Implementation of managed shared_ptr
- * @see Shared
+ * @brief Implementation of managed std::shared_ptr<T>.
+ *
+ * This specialization requires T to be @ref js-concept-class.
  */
 template <typename T>
-class TypeTraits<Shared<T>> {
+class TypeTraits<std::shared_ptr<T>> {
 private:
 	static void apply(ContextPtr ctx, std::shared_ptr<T> value)
 	{
 		StackAssert sa(ctx, 0);
 
-		sign<T>(ctx, -1);
-
-		duk_push_pointer(ctx, new std::shared_ptr<T>(std::move(value)));
+		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<T> *>(duk_to_pointer(ctx, -1));
+			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");
@@ -2251,12 +3027,14 @@
 	 * @param ctx the context
 	 * @param value the value
 	 */
-	static void construct(ContextPtr ctx, Shared<T> 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.object));
+		apply(ctx, std::move(value));
 		duk_pop(ctx);
 	}
 
@@ -2266,115 +3044,55 @@
 	 * @param ctx the context
 	 * @param value the value
 	 */
-	static void push(ContextPtr ctx, Shared<T> 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, value.object);
+		apply(ctx, std::move(value));
 		TypeTraits<T>::prototype(ctx);
 		duk_set_prototype(ctx, -2);
 	}
 
 	/**
-	 * Get a managed shared_ptr from the stack.
+	 * Get a managed std::shared_ptr from the stack.
 	 *
 	 * @param ctx the context
 	 * @param index the object index
-	 * @return the shared_ptr
+	 * @return the pointer or a null if invalid
 	 */
-	static std::shared_ptr<T> get(ContextPtr ctx, int index)
+	static std::shared_ptr<T> get(ContextPtr ctx, Index index)
 	{
-		StackAssert sa(ctx, 0);
-
-		checkSignature<T>(ctx, index);
-
-		duk_get_prop_string(ctx, index, "\xff""\xff""js-shared-ptr");
-		std::shared_ptr<T> value = *static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
-		duk_pop(ctx);
-
-		return value;
-	}
-};
-
-/**
- * @brief Implementation of managed pointers
- * @see Pointer
- */
-template <typename T>
-class TypeTraits<Pointer<T>> {
-private:
-	static void apply(ContextPtr ctx, T *value)
-	{
-		StackAssert sa(ctx, 0);
-
-		sign<T>(ctx, -1);
+		static_assert(std::is_base_of<Bindable, T>::value, "T must be base of Bindable");
 
-		duk_push_pointer(ctx, value);
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-ptr");
-		duk_push_c_function(ctx, [] (duk_context *ctx) -> Ret {
-			duk_get_prop_string(ctx, 0, "\xff""\xff""js-ptr");
-			delete static_cast<T *>(duk_to_pointer(ctx, -1));
-			duk_pop(ctx);
-			duk_push_null(ctx);
-			duk_put_prop_string(ctx, 0, "\xff""\xff""js-ptr");
-
-			return 0;
-		}, 1);
-		duk_set_finalizer(ctx, -2);
-	}
+		StackAssert sa(ctx);
 
-public:
-	/**
-	 * Construct the pointer as this.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void construct(ContextPtr ctx, Pointer<T> value)
-	{
-		StackAssert sa(ctx, 0);
+		auto ptr = getProperty<std::shared_ptr<Bindable> *>(ctx, index, "\xff""\xff""js-shared-ptr");
 
-		duk_push_this(ctx);
-		apply(ctx, value.object);
-		duk_pop(ctx);
+		return (ptr == nullptr) ? nullptr : std::dynamic_pointer_cast<T>(*ptr);
 	}
 
 	/**
-	 * Push a managed pointer as object.
+	 * Require a managed shared_ptr from the stack.
+	 *
+	 * Raise a JavaScript error if the object is not valid.
 	 *
 	 * @param ctx the context
-	 * @param value the value
+	 * @param index the index
+	 * @return the pointer
 	 */
-	static void push(ContextPtr ctx, Pointer<T> value)
+	static std::shared_ptr<T> require(ContextPtr ctx, Index index)
 	{
-		StackAssert sa(ctx, 1);
-
-		duk_push_object(ctx);
-		apply(ctx, value.object);
-		TypeTraits<T>::prototype(ctx);
-		duk_set_prototype(ctx, -2);
-	}
+		static_assert(std::is_base_of<Bindable, T>::value, "T must be base of Bindable");
 
-	/**
-	 * Get a managed pointer from the stack.
-	 *
-	 * @param ctx the context
-	 * @param index the object index
-	 * @return the pointer
-	 * @warning Do not store the pointer into the C++ side, the object can be deleted at any time
-	 */
-	static T *get(ContextPtr ctx, int index)
-	{
-		StackAssert sa(ctx, 0);
+		auto ptr = get(ctx, index);
 
-		checkSignature<T>(ctx, index);
+		if (!ptr)
+			duk::raise(ctx, DUK_ERR_TYPE_ERROR, "invalid this binding");
 
-		duk_get_prop_string(ctx, index, "\xff""\xff""js-ptr");
-		T *value = static_cast<T *>(duk_to_pointer(ctx, -1));
-		duk_pop(ctx);
-
-		return value;
+		return ptr;
 	}
 };
 
@@ -2382,4 +3100,4 @@
 
 } // !malikania
 
-#endif // !MALIKANIA_JS_H
+#endif // !JS_H
--- a/tests/libclient/js-animation/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libclient/js-animation/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -51,7 +51,7 @@
 		loadMalikaniaWindow(m_ctx);
 
 		/* Store the loader */
-		duk::putGlobal(m_ctx, "\xff""\xff""loader", duk::RawPointer<ClientResourcesLoader>{&m_loader});
+		duk::putGlobal(m_ctx, "\xff""\xff""loader", &m_loader);
 	}
 };
 
@@ -65,7 +65,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ElapsedTimer timer;
@@ -80,7 +80,7 @@
 			);
 
 			if (ret != 0) {
-				throw duk::error(m_ctx, -1);
+				throw duk::exception(m_ctx, -1);
 			}
 		}
 
--- a/tests/libclient/js-color/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libclient/js-color/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -52,7 +52,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
@@ -76,7 +76,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "r"));
@@ -100,7 +100,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
@@ -124,7 +124,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "r"));
@@ -148,7 +148,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "r"));
@@ -172,7 +172,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "r"));
@@ -196,7 +196,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "r"));
@@ -223,7 +223,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "r"));
@@ -253,7 +253,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -276,7 +276,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -299,7 +299,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -322,7 +322,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -345,7 +345,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -368,7 +368,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -391,7 +391,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -414,7 +414,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -437,7 +437,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -472,7 +472,7 @@
 		auto ret = duk::pevalString(m_ctx, "draw('#ff0000');");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "r"));
@@ -503,7 +503,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -532,7 +532,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -566,7 +566,7 @@
 		auto ret = duk::pevalString(m_ctx, "draw('#ff0000');");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(255, duk::getGlobal<int>(m_ctx, "r"));
@@ -595,7 +595,7 @@
 		auto ret = duk::pevalString(m_ctx, "draw('#ghijkl');");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
@@ -624,7 +624,7 @@
 		auto ret = duk::pevalString(m_ctx, "draw({ red: -1, green: 256, blue: 100, alpha: 800 });");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
@@ -653,7 +653,7 @@
 		auto ret = duk::pevalString(m_ctx, "draw(null);");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
--- a/tests/libclient/js-font/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libclient/js-font/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -48,7 +48,7 @@
 		loadMalikaniaWindow(m_ctx);
 
 		/* Store the loader */
-		duk::putGlobal(m_ctx, "\xff""\xff""loader", duk::RawPointer<ClientResourcesLoader>{&m_loader});
+		duk::putGlobal(m_ctx, "\xff""\xff""loader", &m_loader);
 	}
 };
 
@@ -68,7 +68,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		std::this_thread::sleep_for(3s);
--- a/tests/libclient/js-image/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libclient/js-image/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -48,7 +48,7 @@
 		loadMalikaniaWindow(m_ctx);
 
 		/* Store the loader */
-		duk::putGlobal(m_ctx, "\xff""\xff""loader", duk::RawPointer<ClientResourcesLoader>{&m_loader});
+		duk::putGlobal(m_ctx, "\xff""\xff""loader", &m_loader);
 	}
 };
 
@@ -62,7 +62,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(32, duk::getGlobal<int>(m_ctx, "w"));
@@ -85,7 +85,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		std::this_thread::sleep_for(3s);
@@ -107,7 +107,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		std::this_thread::sleep_for(3s);
--- a/tests/libclient/js-line/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libclient/js-line/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -52,7 +52,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x1"));
@@ -76,7 +76,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x1"));
@@ -100,7 +100,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x1"));
@@ -124,7 +124,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x1"));
@@ -154,7 +154,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -186,7 +186,7 @@
 		auto ret = duk::pevalString(m_ctx, "build({ x1: 50, y1: 80, x2: 100, y2: 200 });");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(50, duk::getGlobal<int>(m_ctx, "x1"));
@@ -217,7 +217,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -249,7 +249,7 @@
 		auto ret = duk::pevalString(m_ctx, "build({});");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x1"));
--- a/tests/libclient/js-point/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libclient/js-point/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -50,7 +50,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x"));
@@ -70,7 +70,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(-10, duk::getGlobal<int>(m_ctx, "x"));
@@ -90,7 +90,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "x"));
@@ -110,7 +110,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "x"));
@@ -138,7 +138,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -168,7 +168,7 @@
 		auto ret = duk::pevalString(m_ctx, "build({ x: 100, y: 200 });");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "x"));
@@ -197,7 +197,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -227,7 +227,7 @@
 		auto ret = duk::pevalString(m_ctx, "build({});");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x"));
--- a/tests/libclient/js-rectangle/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libclient/js-rectangle/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -52,7 +52,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x"));
@@ -76,7 +76,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x"));
@@ -100,7 +100,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x"));
@@ -124,7 +124,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(10, duk::getGlobal<int>(m_ctx, "x"));
@@ -154,7 +154,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -177,7 +177,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -209,7 +209,7 @@
 		auto ret = duk::pevalString(m_ctx, "build({ x: 50, y: 80, width: 100, height: 200 });");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(50, duk::getGlobal<int>(m_ctx, "x"));
@@ -240,7 +240,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -272,7 +272,7 @@
 		auto ret = duk::pevalString(m_ctx, "build({});");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "x"));
--- a/tests/libclient/js-size/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libclient/js-size/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -50,7 +50,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "w"));
@@ -70,7 +70,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "w"));
@@ -90,7 +90,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "w"));
@@ -110,7 +110,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "w"));
@@ -138,7 +138,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("TypeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -161,7 +161,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -184,7 +184,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -207,7 +207,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -230,7 +230,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("RangeError", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -260,7 +260,7 @@
 		auto ret = duk::pevalString(m_ctx, "build({ width: 100, height: 200 });");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(100, duk::getGlobal<int>(m_ctx, "w"));
@@ -289,7 +289,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ("Error", duk::getGlobal<std::string>(m_ctx, "name"));
@@ -319,7 +319,7 @@
 		auto ret = duk::pevalString(m_ctx, "build({});");
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(0, duk::getGlobal<int>(m_ctx, "r"));
--- a/tests/libclient/js-sprite/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libclient/js-sprite/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -50,7 +50,7 @@
 		loadMalikaniaWindow(m_ctx);
 
 		/* Store the loader */
-		duk::putGlobal(m_ctx, "\xff""\xff""loader", duk::RawPointer<ClientResourcesLoader>{&m_loader});
+		duk::putGlobal(m_ctx, "\xff""\xff""loader", &m_loader);
 	}
 };
 
@@ -64,7 +64,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(32, duk::getGlobal<int>(m_ctx, "w"));
@@ -83,7 +83,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(4, duk::getGlobal<int>(m_ctx, "n"));
@@ -102,7 +102,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(4, duk::getGlobal<int>(m_ctx, "w"));
@@ -121,7 +121,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(3, duk::getGlobal<int>(m_ctx, "n"));
@@ -140,7 +140,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		ASSERT_EQ(2, duk::getGlobal<int>(m_ctx, "w"));
@@ -160,7 +160,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		for (unsigned c = 0; c < 12; ++c) {
@@ -172,7 +172,7 @@
 			);
 
 			if (ret != 0) {
-				throw duk::error(m_ctx, -1);
+				throw duk::exception(m_ctx, -1);
 			}
 
 			std::this_thread::sleep_for(1s);
--- a/tests/libclient/js-window/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libclient/js-window/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -51,7 +51,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		std::this_thread::sleep_for(3s);
@@ -73,7 +73,7 @@
 		);
 
 		if (ret != 0) {
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 		}
 
 		std::this_thread::sleep_for(3s);
--- a/tests/libcommon/js-elapsed-timer/main.cpp	Fri Apr 08 14:16:47 2016 +0200
+++ b/tests/libcommon/js-elapsed-timer/main.cpp	Tue Apr 12 13:53:11 2016 +0200
@@ -53,12 +53,12 @@
 {
 	try {
 		if (duk::pevalString(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		std::this_thread::sleep_for(300ms);
 
 		if (duk::pevalString(m_ctx, "result = timer.elapsed();") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		assertRange(duk::getGlobal<int>(m_ctx, "result"), 300);
 	} catch (const std::exception &ex) {
@@ -70,12 +70,12 @@
 {
 	try {
 		if (duk::pevalString(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		std::this_thread::sleep_for(300ms);
 
 		if (duk::pevalString(m_ctx, "timer.reset(); result = timer.elapsed();") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		assertRange(duk::getGlobal<int>(m_ctx, "result"), 0);
 	} catch (const std::exception &ex) {
@@ -87,7 +87,7 @@
 {
 	try {
 		if (duk::pevalString(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		/*
 		 * Simulate a pause in the game like this:
@@ -100,17 +100,17 @@
 		std::this_thread::sleep_for(10ms);
 
 		if (duk::pevalString(m_ctx, "timer.pause();") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		std::this_thread::sleep_for(5ms);
 
 		if (duk::pevalString(m_ctx, "timer.restart();") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		std::this_thread::sleep_for(6ms);
 
 		if (duk::pevalString(m_ctx, "result = timer.elapsed()") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		assertRange(duk::getGlobal<int>(m_ctx, "result"), 16);
 	} catch (const std::exception &ex) {
@@ -122,17 +122,17 @@
 {
 	try {
 		if (duk::pevalString(m_ctx, "timer = new Malikania.ElapsedTimer();") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		std::this_thread::sleep_for(50ms);
 
 		if (duk::pevalString(m_ctx, "result = timer.elapsed()") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		std::this_thread::sleep_for(50ms);
 
 		if (duk::pevalString(m_ctx, "result = timer.elapsed()") != 0)
-			throw duk::error(m_ctx, -1);
+			throw duk::exception(m_ctx, -1);
 
 		assertRange(duk::getGlobal<int>(m_ctx, "result"), 100);
 	} catch (const std::exception &ex) {