changeset 433:70bcc6962c88

Js: fix destruction error and switch to LF lines
author David Demelier <markand@malikania.fr>
date Mon, 19 Oct 2015 13:57:52 +0200
parents 88df9c580c36
children da92b98de599
files C++/modules/Js/Js.cpp C++/modules/Js/Js.h C++/tests/Js/main.cpp
diffstat 3 files changed, 2232 insertions(+), 2195 deletions(-) [+]
line wrap: on
line diff
--- a/C++/modules/Js/Js.cpp	Fri Oct 16 08:50:20 2015 +0200
+++ b/C++/modules/Js/Js.cpp	Mon Oct 19 13:57:52 2015 +0200
@@ -1,107 +1,107 @@
-/*
- * Js.cpp -- JavaScript C++14 wrapper for Duktape
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "Js.h"
-
-using namespace std::string_literals;
-
-namespace js {
-
-ErrorInfo Context::error(int index)
-{
-	ErrorInfo error;
-
-	index = duk_normalize_index(m_handle.get(), index);
-
-	duk_get_prop_string(m_handle.get(), index, "name");
-	error.name = duk_to_string(m_handle.get(), -1);
-	duk_get_prop_string(m_handle.get(), index, "message");
-	error.message = duk_to_string(m_handle.get(), -1);
-	duk_get_prop_string(m_handle.get(), index, "fileName");
-	error.fileName = duk_to_string(m_handle.get(), -1);
-	duk_get_prop_string(m_handle.get(), index, "lineNumber");
-	error.lineNumber = duk_to_int(m_handle.get(), -1);
-	duk_get_prop_string(m_handle.get(), index, "stack");
-	error.stack = duk_to_string(m_handle.get(), -1);
-	duk_pop_n(m_handle.get(), 5);
-
-	return error;
-}
-
-void Context::pcall(unsigned nargs)
-{
-	if (duk_pcall(m_handle.get(), nargs) != 0) {
-		ErrorInfo info = error(-1);
-		duk_pop(m_handle.get());
-
-		throw info;
-	}
-}
-
-void Context::peval()
-{
-	if (duk_peval(m_handle.get()) != 0) {
-		ErrorInfo info = error(-1);
-		duk_pop(m_handle.get());
-
-		throw info;
-	}
-}
-
-void TypeInfo<Function>::push(Context &ctx, Function fn)
-{
-	/* 1. Push function wrapper */
-	duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
-		Context context{ctx};
-
-		duk_push_current_function(ctx);
-		duk_get_prop_string(ctx, -1, "\xff""\xff""js-func");
-		Function *f = static_cast<Function *>(duk_to_pointer(ctx, -1));
-		duk_pop_2(ctx);
-
-		return static_cast<duk_ret_t>(f->function(context));
-	}, fn.nargs);
-
-	/* 2. Store the moved function */
-	duk_push_pointer(ctx, new Function(std::move(fn)));
-	duk_put_prop_string(ctx, -2, "\xff""\xff""js-func");
-
-	/* 3. Store deletion flags */
-	duk_push_boolean(ctx, false);
-	duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
-
-	/* 4. Push and set a finalizer */
-	duk_push_c_function(ctx, [] (duk_context *ctx) {
-		duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-
-		if (duk_to_boolean(ctx, -1)) {
-			duk_push_boolean(ctx, true);
-			duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-			duk_get_prop_string(ctx, 0, "\xff""\xff""js-func");
-			delete static_cast<Function *>(duk_to_pointer(ctx, -1));
-			duk_pop(ctx);
-		}
-
-		duk_pop(ctx);
-
-		return 0;
-	}, 1);
-	duk_set_finalizer(ctx, -2);
-}
-
-} // !js
+/*
+ * Js.cpp -- JavaScript C++14 wrapper for Duktape
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "Js.h"
+
+using namespace std::string_literals;
+
+namespace js {
+
+ErrorInfo Context::error(int index)
+{
+	ErrorInfo error;
+
+	index = duk_normalize_index(m_handle.get(), index);
+
+	duk_get_prop_string(m_handle.get(), index, "name");
+	error.name = duk_to_string(m_handle.get(), -1);
+	duk_get_prop_string(m_handle.get(), index, "message");
+	error.message = duk_to_string(m_handle.get(), -1);
+	duk_get_prop_string(m_handle.get(), index, "fileName");
+	error.fileName = duk_to_string(m_handle.get(), -1);
+	duk_get_prop_string(m_handle.get(), index, "lineNumber");
+	error.lineNumber = duk_to_int(m_handle.get(), -1);
+	duk_get_prop_string(m_handle.get(), index, "stack");
+	error.stack = duk_to_string(m_handle.get(), -1);
+	duk_pop_n(m_handle.get(), 5);
+
+	return error;
+}
+
+void Context::pcall(unsigned nargs)
+{
+	if (duk_pcall(m_handle.get(), nargs) != 0) {
+		ErrorInfo info = error(-1);
+		duk_pop(m_handle.get());
+
+		throw info;
+	}
+}
+
+void Context::peval()
+{
+	if (duk_peval(m_handle.get()) != 0) {
+		ErrorInfo info = error(-1);
+		duk_pop(m_handle.get());
+
+		throw info;
+	}
+}
+
+void TypeInfo<Function>::push(Context &ctx, Function fn)
+{
+	/* 1. Push function wrapper */
+	duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
+		Context context{ctx};
+
+		duk_push_current_function(ctx);
+		duk_get_prop_string(ctx, -1, "\xff""\xff""js-func");
+		Function *f = static_cast<Function *>(duk_to_pointer(ctx, -1));
+		duk_pop_2(ctx);
+
+		return static_cast<duk_ret_t>(f->function(context));
+	}, fn.nargs);
+
+	/* 2. Store the moved function */
+	duk_push_pointer(ctx, new Function(std::move(fn)));
+	duk_put_prop_string(ctx, -2, "\xff""\xff""js-func");
+
+	/* 3. Store deletion flags */
+	duk_push_boolean(ctx, false);
+	duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
+
+	/* 4. Push and set a finalizer */
+	duk_push_c_function(ctx, [] (duk_context *ctx) {
+		duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+
+		if (!duk_to_boolean(ctx, -1)) {
+			duk_push_boolean(ctx, true);
+			duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+			duk_get_prop_string(ctx, 0, "\xff""\xff""js-func");
+			delete static_cast<Function *>(duk_to_pointer(ctx, -1));
+			duk_pop(ctx);
+		}
+
+		duk_pop(ctx);
+
+		return 0;
+	}, 1);
+	duk_set_finalizer(ctx, -2);
+}
+
+} // !js
--- a/C++/modules/Js/Js.h	Fri Oct 16 08:50:20 2015 +0200
+++ b/C++/modules/Js/Js.h	Mon Oct 19 13:57:52 2015 +0200
@@ -1,2067 +1,2067 @@
-/*
- * Js.h -- JavaScript C++14 wrapper for Duktape
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _JS_H_
-#define _JS_H_
-
-/**
- * @file Js.h
- * @brief Bring JavaScript using Duktape
- *
- * This file provides usual Duktape function renamed and placed into `js` namespace. It also replaces error
- * code with exceptions when possible.
- *
- * For convenience, this file also provides templated functions, overloads and much more.
- */
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <type_traits>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include <duktape.h>
-
-/**
- * Duktape C++ namespace wrapper.
- */
-namespace js {
-
-class Context;
-
-/**
- * Typedef for readability.
- */
-using ContextPtr = duk_context *;
-
-/*
- * Basic types to manipulate with the stack
- * ------------------------------------------------------------------
- *
- * The following types can be used in some of the operations like Context::push or Context::is, they are defined
- * usually as empty classes to determine the appropriate action to execute.
- *
- * For example, `ctx.push(js::Object{})` will push an empty object into the stack.
- */
-
-/**
- * @class Object
- * @brief Empty class tag for push() function.
- */
-class Object {
-};
-
-/**
- * @class Array
- * @brief Empty class tag for push() function.
- */
-class Array {
-};
-
-/**
- * @class Global
- * @brief Empty class tag to push the global object.
- */
-class Global {
-};
-
-/**
- * @class Undefined
- * @brief Empty class tag to push undefined to the stack.
- */
-class Undefined {
-};
-
-/**
- * @class Null
- * @brief Empty class tag to push null to the stack.
- */
-class Null {
-};
-
-/**
- * @class This
- * @brief Empty class tag to push this binding to the stack.
- */
-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;
-};
-
-/*
- * Extended type manipulation
- * ------------------------------------------------------------------
- *
- * The following types are different as there are no equivalent in the native Duktape API, they are available for
- * convenience.
- */
-
-/**
- * @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.
- *
- * The only requirement is to have the function `void prototype(Context &ctx)` in your class T.
- */
-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.
- *
- * This class wraps the std::function as a Duktape/C function by storing a copied pointer.
- */
-class Function {
-public:
-	/**
-	 * The function pointer, must not be null.
-	 */
-	std::function<int (Context &)> function;
-
-	/**
-	 * Number of args that the function takes
-	 */
-	int nargs{0};
-};
-
-/**
- * Map of functions to set on an object.
- */
-using FunctionMap = std::unordered_map<std::string, Function>;
-
-/**
- * Map of string to type, ideal for setting constants like enums.
- */
-template <typename Type>
-using Map = std::unordered_map<std::string, Type>;
-
-/**
- * @class ErrorInfo
- * @brief Error description.
- *
- * This class fills the fields got in an Error object.
- */
-class ErrorInfo : public std::exception {
-public:
-	std::string name;		//!< name of error
-	std::string message;		//!< error message
-	std::string stack;		//!< stack if available
-	std::string fileName;		//!< filename if applicable
-	int lineNumber{0};		//!< line number if applicable
-
-	/**
-	 * Get the error message. This effectively returns message field.
-	 *
-	 * @return the message
-	 */
-	const char *what() const noexcept override
-	{
-		return message.c_str();
-	}
-};
-
-/**
- * @class TypeInfo
- * @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 TypeInfo {
-};
-
-/**
- * @class File
- * @brief Evaluate script from file.
- * @see Context::eval
- * @see Context::peval
- */
-class File {
-public:
-	/**
-	 * Path to the file.
-	 */
-	std::string path;
-
-	/**
-	 * Evaluate the file.
-	 *
-	 * @param ctx the context
-	 */
-	inline void eval(duk_context *ctx)
-	{
-		duk_eval_file(ctx, path.c_str());
-	}
-
-	/**
-	 * Evaluate in protected mode the file.
-	 *
-	 * @param ctx the context
-	 */
-	inline int peval(duk_context *ctx)
-	{
-		return duk_peval_file(ctx, path.c_str());
-	}
-};
-
-/**
- * @class Script
- * @brief Evaluate script from raw text.
- * @see Context::eval
- * @see Context::peval
- */
-class Script {
-public:
-	/**
-	 * The script content.
-	 */
-	std::string text;
-
-	/**
-	 * Evaluate the script.
-	 *
-	 * @param ctx the context
-	 */
-	inline void eval(duk_context *ctx)
-	{
-		duk_eval_string(ctx, text.c_str());
-	}
-
-	/**
-	 * Evaluate in protected mode the script.
-	 *
-	 * @param ctx the context
-	 */
-	inline int peval(duk_context *ctx)
-	{
-		return duk_peval_string(ctx, text.c_str());
-	}
-};
-
-/**
- * @class Context
- * @brief RAII based Duktape handler.
- *
- * This class is implicitly convertible to duk_context for convenience.
- */
-class Context {
-private:
-	using Deleter = void (*)(duk_context *);
-	using Handle = std::unique_ptr<duk_context, Deleter>;
-
-	Handle m_handle;
-
-	/* Move and copy forbidden */
-	Context(const Context &) = delete;
-	Context &operator=(const Context &) = delete;
-	Context(const Context &&) = delete;
-	Context &operator=(const Context &&) = delete;
-
-public:
-	/**
-	 * Create default context.
-	 */
-	inline Context()
-		: m_handle{duk_create_heap_default(), duk_destroy_heap}
-	{
-	}
-
-	/**
-	 * Create borrowed context that will not be deleted.
-	 *
-	 * @param ctx the pointer to duk_context
-	 */
-	inline Context(ContextPtr ctx) noexcept
-		: m_handle{ctx, [] (ContextPtr) {}}
-	{
-	}
-
-	/**
-	 * Convert the context to the native Duktape/C type.
-	 *
-	 * @return the duk_context
-	 */
-	inline operator duk_context *() noexcept
-	{
-		return m_handle.get();
-	}
-
-	/**
-	 * Convert the context to the native Duktape/C type.
-	 *
-	 * @return the duk_context
-	 */
-	inline operator duk_context *() const noexcept
-	{
-		return m_handle.get();
-	}
-
-	/*
-	 * Basic functions
-	 * ----------------------------------------------------------
-	 *
-	 * The following functions are just standard wrappers around the native Duktape C functions, they are
-	 * defined with the same signature except that for convenience some parameters have default sane values.
-	 */
-
-	/**
-	 * Call the object at the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param nargs the number of arguments
-	 * @note Non-protected
-	 */
-	inline void call(unsigned nargs = 0)
-	{
-		duk_call(m_handle.get(), nargs);
-	}
-
-	/**
-	 * Copy a value from from to to, overwriting the previous value. If either index is invalid, throws an error.
-	 *
-	 * @param from the from index
-	 * @param to the destination
-	 */
-	inline void copy(int from, int to)
-	{
-		duk_copy(m_handle.get(), from, to);
-	}
-
-	/**
-	 * Define a property.
-	 *
-	 * @param index the object index
-	 * @param flags the flags
-	 * @note Wrapper of duk_def_prop
-	 */
-	inline void defineProperty(int index, int flags)
-	{
-		duk_def_prop(m_handle.get(), index, flags);
-	}
-
-	/**
-	 * Delete a property.
-	 *
-	 * @param index the object index
-	 * @return true if deleted
-	 * @note Wrapper of duk_del_prop
-	 */
-	inline bool deleteProperty(int index)
-	{
-		return duk_del_prop(m_handle.get(), index);
-	}
-
-	/**
-	 * Delete a property by index.
-	 *
-	 * @param index the object index
-	 * @param position the property index
-	 * @return true if deleted
-	 * @note Wrapper of duk_del_prop_index
-	 */
-	inline bool deleteProperty(int index, int position)
-	{
-		return duk_del_prop_index(m_handle.get(), index, position);
-	}
-
-	/**
-	 * Delete a property by name.
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @return true if deleted
-	 * @note Wrapper of duk_del_prop_string
-	 */
-	inline bool deleteProperty(int index, const std::string &name)
-	{
-		return duk_del_prop_string(m_handle.get(), index, name.c_str());
-	}
-
-	/**
-	 * Push a duplicate of value at from_index to the stack. If from_index is invalid, throws an error.
-	 *
-	 * @param index the value to copy
-	 * @note Wrapper of duk_dup
-	 */
-	inline void dup(int index = -1)
-	{
-		duk_dup(m_handle.get(), index);
-	}
-
-	/**
-	 * Evaluate a non-protected chunk that is at the top of the stack.
-	 */
-	inline void eval()
-	{
-		duk_eval(m_handle.get());
-	}
-
-	/**
-	 * Check if the object as a property.
-	 *
-	 * @param index the object index
-	 * @return true if has
-	 * @note Wrapper of duk_has_prop
-	 */
-	inline bool hasProperty(int index)
-	{
-		return duk_has_prop(m_handle.get(), index);
-	}
-
-	/**
-	 * Check if the object as a property by index.
-	 *
-	 * @param index the object index
-	 * @param position the property index
-	 * @return true if has
-	 * @note Wrapper of duk_has_prop_index
-	 */
-	inline bool hasProperty(int index, int position)
-	{
-		return duk_has_prop_index(m_handle.get(), index, position);
-	}
-
-	/**
-	 * Check if the object as a property by string
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @return true if has
-	 * @note Wrapper of duk_has_prop_string
-	 */
-	inline bool hasProperty(int index, const std::string &name)
-	{
-		return duk_has_prop_string(m_handle.get(), index, name.c_str());
-	}
-
-	/**
-	 * Check if idx1 is an instance of idx2.
-	 *
-	 * @param ctx the context
-	 * @param idx1 the value to test
-	 * @param idx2 the instance requested
-	 * @return true if idx1 is instance of idx2
-	 * @note Wrapper of duk_instanceof
-	 */
-	inline bool instanceof(int idx1, int idx2)
-	{
-		return duk_instanceof(m_handle.get(), idx1, idx2);
-	}
-
-	/**
-	 * Insert a value at to with a value popped from the stack top. The previous value at to and any values above
-	 * it are moved up the stack by a step. If to is an invalid index, throws an error.
-	 *
-	 * @note Negative indices are evaluated prior to popping the value at the stack top
-	 * @param to the destination
-	 * @note Wrapper of duk_insert
-	 */
-	inline void insert(int to)
-	{
-		duk_insert(m_handle.get(), to);
-	}
-
-	/**
-	 * Pop a certain number of values from the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param count the number of values to pop
-	 * @note Wrapper of duk_pop_n
-	 */
-	inline void pop(unsigned count = 1)
-	{
-		duk_pop_n(m_handle.get(), count);
-	}
-
-	/**
-	 * Remove value at index. Elements above index are shifted down the stack by a step. If to is an invalid index,
-	 * throws an error.
-	 *
-	 * @param index the value to remove
-	 * @note Wrapper of duk_remove
-	 */
-	inline void remove(int index)
-	{
-		duk_remove(m_handle.get(), index);
-	}
-
-	/**
-	 * Replace value at to_index with a value popped from the stack top. If to_index is an invalid index,
-	 * throws an error.
-	 *
-	 * @param index the value to replace by the value at the top of the stack
-	 * @note Negative indices are evaluated prior to popping the value at the stack top.
-	 * @note Wrapper of duk_replace
-	 */
-	inline void replace(int index)
-	{
-		duk_replace(m_handle.get(), index);
-	}
-
-	/**
-	 * Swap values at indices index1 and index2. If the indices are the same, the call is a no-op. If either index
-	 * is invalid, throws an error.
-	 *
-	 * @param index1 the first index
-	 * @param index2 the second index
-	 * @note Wrapper of duk_swap
-	 */
-	inline void swap(int index1, int index2)
-	{
-		duk_swap(m_handle.get(), index1, index2);
-	}
-
-	/**
-	 * Get the current stack size.
-	 *
-	 * @param ctx the context
-	 * @return the stack size
-	 * @note Wrapper of duk_get_top
-	 */
-	inline int top() noexcept
-	{
-		return duk_get_top(m_handle.get());
-	}
-
-	/**
-	 * Get the type of the value at the specified index.
-	 *
-	 * @param ctx the context
-	 * @param index the idnex
-	 * @return the type
-	 * @note Wrapper of duk_get_type
-	 */
-	inline int type(int index) noexcept
-	{
-		return duk_get_type(m_handle.get(), index);
-	}
-
-	/*
-	 * Extended native functions
-	 * ----------------------------------------------------------
-	 *
-	 * The following functions have different behaviour than the original native Duktape C functions, see their
-	 * descriptions for more information
-	 */
-
-	/**
-	 * Call in protected mode the object at the top of the stack.
-	 *
-	 * @param nargs the number of arguments
-	 * @throw ErrorInfo on errors
-	 * @note Wrapper of duk_pcall
-	 */
-	void pcall(unsigned nargs = 0);
-
-	/**
-	 * Evaluate a non-protected source.
-	 *
-	 * @param source the source
-	 * @see File
-	 * @see Script
-	 * @note Wrapper of duk_eval
-	 */
-	template <typename Source>
-	inline void eval(Source &&source)
-	{
-		source.eval(m_handle.get());
-	}
-
-	/**
-	 * Evaluate a protected chunk that is at the top of the stack.
-	 *
-	 * @throw ErrorInfo the error
-	 * @note Wrapper of duk_peval
-	 */
-	void peval();
-
-	/**
-	 * Evaluate a protected source.
-	 *
-	 * @param source the source
-	 * @see File
-	 * @see Script
-	 * @throw ErrorInfo on failure
-	 * @note Wrapper of duk_peval
-	 */
-	template <typename Source>
-	inline void peval(Source &&source)
-	{
-		if (source.peval(m_handle.get()) != 0) {
-			ErrorInfo info = error(-1);
-			duk_pop(m_handle.get());
-
-			throw info;
-		}
-	}
-
-	/*
-	 * Push / Get / Require / Is / Optional
-	 * ----------------------------------------------------------
-	 *
-	 * The following functions are used to push, get or check values from the stack. They use specialization
-	 * of TypeInfo class.
-	 */
-
-	/**
-	 * Push a value into the stack. Calls TypeInfo<T>::push(*this, value);
-	 *
-	 * @param value the value to forward
-	 */
-	template <typename Type>
-	inline void push(Type &&value)
-	{
-		TypeInfo<std::decay_t<Type>>::push(*this, std::forward<Type>(value));
-	}
-
-	/**
-	 * Generic template function to get a value from the stack.
-	 *
-	 * @param index the index
-	 * @return the value
-	 */
-	template <typename Type>
-	inline auto get(int index) -> decltype(TypeInfo<Type>::get(*this, 0))
-	{
-		return TypeInfo<Type>::get(*this, index);
-	}
-
-	/**
-	 * Require a type at the specified index.
-	 *
-	 * @param index the index
-	 * @return the value
-	 */
-	template <typename Type>
-	inline auto require(int index) -> decltype(TypeInfo<Type>::require(*this, 0))
-	{
-		return TypeInfo<Type>::require(*this, index);
-	}
-
-	/**
-	 * Check if a value is a type of T.
-	 *
-	 * The TypeInfo<T> must have `static bool is(ContextPtr ptr, int index)`.
-	 *
-	 * @param index the value index
-	 * @return true if is the type
-	 */
-	template <typename T>
-	inline bool is(int index)
-	{
-		return TypeInfo<T>::is(*this, index);
-	}
-
-	/**
-	 * Get an optional value from the stack, if the value is not available of not the correct type,
-	 * return defaultValue instead.
-	 *
-	 * The TypeInfo<T> must have `static T optional(Context &, int index, T &&defaultValue)`.
-	 *
-	 * @param index the value index
-	 * @param defaultValue the value replacement
-	 * @return the value or defaultValue
-	 */
-	template <typename Type>
-	inline auto optional(int index, Type &&defaultValue)
-	{
-		return TypeInfo<std::decay_t<Type>>::optional(*this, index, std::forward<Type>(defaultValue));
-	}
-
-	/*
-	 * Properties management
-	 * ----------------------------------------------------------
-	 *
-	 * The following functions are used to read or set properties on objects or globals also using TypeInfo.
-	 */
-
-	/**
-	 * Get the property `name' as value from the object at the specified index.
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @return the value
-	 * @note The stack is unchanged
-	 */
-	template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
-	inline auto getProperty(int index, const std::string &name) -> decltype(get<Type>(0))
-	{
-		duk_get_prop_string(m_handle.get(), index, name.c_str());
-		decltype(get<Type>(0)) value = get<Type>(-1);
-		duk_pop(m_handle.get());
-
-		return value;
-	}
-
-	/**
-	 * Get a property by index, for arrays.
-	 *
-	 * @param index the object index
-	 * @param position the position int the object
-	 * @return the value
-	 * @note The stack is unchanged
-	 */
-	template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
-	inline auto getProperty(int index, int position) -> decltype(get<Type>(0))
-	{
-		duk_get_prop_index(m_handle.get(), index, position);
-		decltype(get<Type>(0)) value = get<Type>(-1);
-		duk_pop(m_handle.get());
-
-		return value;
-	}
-
-	/**
-	 * Get the property `name' and push it to the stack from the object at the specified index.
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @note The stack contains the property value
-	 */
-	template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
-	inline void getProperty(int index, const std::string &name)
-	{
-		duk_get_prop_string(m_handle.get(), index, name.c_str());
-	}
-
-	/**
-	 * Get the property by index and push it to the stack from the object at the specified index.
-	 *
-	 * @param index the object index
-	 * @param position the position in the object
-	 * @note The stack contains the property value
-	 */
-	template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
-	inline void getProperty(int index, int position)
-	{
-		duk_get_prop_index(m_handle.get(), index, position);
-	}
-
-	/**
-	 * Set a property to the object at the specified index.
-	 *
-	 * @param index the object index
-	 * @param name the property name
-	 * @param value the value to forward
-	 * @note The stack is unchanged
-	 */
-	template <typename Type>
-	void putProperty(int index, const std::string &name, Type &&value)
-	{
-		index = duk_normalize_index(m_handle.get(), index);
-
-		push(std::forward<Type>(value));
-		duk_put_prop_string(m_handle.get(), index, name.c_str());
-	}
-
-	/**
-	 * Set a property by index, for arrays.
-	 *
-	 * @param index the object index
-	 * @param position the position in the object
-	 * @param value the value to forward
-	 * @note The stack is unchanged
-	 */
-	template <typename Type>
-	void putProperty(int index, int position, Type &&value)
-	{
-		index = duk_normalize_index(m_handle.get(), index);
-
-		push(std::forward<Type>(value));
-		duk_put_prop_index(m_handle.get(), index, position);
-	}
-
-	/**
-	 * 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(int index, const std::string &name)
-	{
-		duk_put_prop_string(m_handle.get(), 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(int index, int position)
-	{
-		duk_put_prop_index(m_handle.get(), index, position);
-	}
-
-	/**
-	 * Get a global value.
-	 *
-	 * @param name the name of the global variable
-	 * @return the value
-	 */
-	template <typename Type>
-	inline auto getGlobal(const std::string &name, std::enable_if_t<!std::is_void<Type>::value> * = nullptr) -> decltype(get<Type>(0))
-	{
-		duk_get_global_string(m_handle.get(), name.c_str());
-		decltype(get<Type>(0)) value = get<Type>(-1);
-		duk_pop(m_handle.get());
-
-		return value;
-	}
-
-	/**
-	 * Overload that push the value at the top of the stack instead of returning it.
-	 */
-	template <typename Type>
-	inline void getGlobal(const std::string &name, std::enable_if_t<std::is_void<Type>::value> * = nullptr) noexcept
-	{
-		duk_get_global_string(m_handle.get(), name.c_str());
-	}
-
-	/**
-	 * Set a global variable.
-	 *
-	 * @param name the name of the global variable
-	 * @param type the value to set
-	 */
-	template <typename Type>
-	inline void putGlobal(const std::string &name, Type&& type)
-	{
-		push(std::forward<Type>(type));
-		duk_put_global_string(m_handle.get(), name.c_str());
-	}
-
-	/**
-	 * Put the value at the top of the stack as global property.
-	 *
-	 * @param name the property name
-	 */
-	inline void putGlobal(const std::string &name)
-	{
-		duk_put_global_string(m_handle.get(), name.c_str());
-	}
-
-	/*
-	 * Extra functions
-	 * ----------------------------------------------------------
-	 *
-	 * The following functions are implemented for convenience and do not exists in the native Duktape API.
-	 */
-
-	/**
-	 * Get the error object when a JavaScript error has been thrown (e.g. eval failure).
-	 *
-	 * @param index the index
-	 * @return the information
-	 */
-	ErrorInfo error(int index);
-
-	/**
-	 * Enumerate an object or an array at the specified index.
-	 *
-	 * @param index the object or array index
-	 * @param flags the optional flags to pass to duk_enum
-	 * @param getvalue set to true if you want to extract the value
-	 * @param func the function to call for each properties
-	 */
-	template <typename Func>
-	void enumerate(int index, duk_uint_t flags, duk_bool_t getvalue, Func&& func)
-	{
-		duk_enum(m_handle.get(), index, flags);
-
-		while (duk_next(m_handle.get(), -1, getvalue)) {
-			func(*this);
-			duk_pop_n(m_handle.get(), 1 + (getvalue ? 1 : 0));
-		}
-
-		duk_pop(m_handle.get());
-	}
-
-	/**
-	 * Return the this binding of the current function.
-	 *
-	 * @return the this binding as the template given
-	 */
-	template <typename T>
-	inline auto self() -> decltype(TypeInfo<T>::get(*this, 0))
-	{
-		duk_push_this(m_handle.get());
-		decltype(TypeInfo<T>::get(*this, 0)) value = TypeInfo<T>::get(*this, -1);
-		duk_pop(m_handle.get());
-
-		return value;
-	}
-
-	/**
-	 * Throw an ECMAScript exception.
-	 *
-	 * @param ex the exception
-	 */
-	template <typename Exception>
-	void raise(const Exception &ex)
-	{
-		ex.create(m_handle.get());
-
-		duk_push_string(m_handle.get(), ex.name().c_str());
-		duk_put_prop_string(m_handle.get(), -2, "name");
-		duk_throw(m_handle.get());
-	}
-
-	/**
-	 * Construct the object in place, setting value as this binding.
-	 *
-	 * The TypeInfo<T> must have the following requirements:
-	 *
-	 * - static void construct(Context &, T): must update this with the value and keep the stack unchanged
-	 *
-	 * @param value the value to forward
-	 * @see self
-	 */
-	template <typename T>
-	inline void construct(T &&value)
-	{
-		TypeInfo<std::decay_t<T>>::construct(*this, std::forward<T>(value));
-	}
-};
-
-/* ------------------------------------------------------------------
- * Exception handling
- * ------------------------------------------------------------------ */
-
-/**
- * @class Error
- * @brief Base ECMAScript error class.
- * @warning Override the function create for your own exceptions
- */
-class Error {
-protected:
-	std::string m_name;	//!< Name of exception (e.g RangeError)
-	std::string m_message;	//!< The message
-
-	/**
-	 * Constructor with a type of error specified, specially designed for derived errors.
-	 *
-	 * @param name the error name (e.g RangeError)
-	 * @param message the message
-	 */
-	inline Error(std::string name, std::string message) noexcept
-		: m_name{std::move(name)}
-		, m_message{std::move(message)}
-	{
-	}
-
-public:
-	/**
-	 * Constructor with a message.
-	 *
-	 * @param message the message
-	 */
-	inline Error(std::string message) noexcept
-		: m_name{"Error"}
-		, m_message{std::move(message)}
-	{
-	}
-
-	/**
-	 * Get the error type (e.g RangeError).
-	 *
-	 * @return the name
-	 */
-	inline const std::string &name() const noexcept
-	{
-		return m_name;
-	}
-
-	/**
-	 * Create the exception on the stack.
-	 *
-	 * @note the default implementation search for the global variables
-	 * @param ctx the context
-	 */
-	virtual void create(ContextPtr ctx) const noexcept
-	{
-		duk_get_global_string(ctx, m_name.c_str());
-		duk_push_string(ctx, m_message.c_str());
-		duk_new(ctx, 1);
-	}
-};
-
-/**
- * @class EvalError
- * @brief Error in eval() function.
- */
-class EvalError : public Error {
-public:
-	/**
-	 * Construct an EvalError.
-	 *
-	 * @param message the message
-	 */
-	inline EvalError(std::string message) noexcept
-		: Error{"EvalError", std::move(message)}
-	{
-	}
-};
-
-/**
- * @class RangeError
- * @brief Value is out of range.
- */
-class RangeError : public Error {
-public:
-	/**
-	 * Construct an RangeError.
-	 *
-	 * @param message the message
-	 */
-	inline RangeError(std::string message) noexcept
-		: Error{"RangeError", std::move(message)}
-	{
-	}
-};
-
-/**
- * @class ReferenceError
- * @brief Trying to use a variable that does not exist.
- */
-class ReferenceError : public Error {
-public:
-	/**
-	 * Construct an ReferenceError.
-	 *
-	 * @param message the message
-	 */
-	inline ReferenceError(std::string message) noexcept
-		: Error{"ReferenceError", std::move(message)}
-	{
-	}
-};
-
-/**
- * @class SyntaxError
- * @brief Syntax error in the script.
- */
-class SyntaxError : public Error {
-public:
-	/**
-	 * Construct an SyntaxError.
-	 *
-	 * @param message the message
-	 */
-	inline SyntaxError(std::string message) noexcept
-		: Error{"SyntaxError", std::move(message)}
-	{
-	}
-};
-
-/**
- * @class TypeError
- * @brief Invalid type given.
- */
-class TypeError : public Error {
-public:
-	/**
-	 * Construct an TypeError.
-	 *
-	 * @param message the message
-	 */
-	inline TypeError(std::string message) noexcept
-		: Error{"TypeError", std::move(message)}
-	{
-	}
-};
-
-/**
- * @class URIError
- * @brief URI manipulation failure.
- */
-class URIError : public Error {
-public:
-	/**
-	 * Construct an URIError.
-	 *
-	 * @param message the message
-	 */
-	inline URIError(std::string message) noexcept
-		: Error{"URIError", std::move(message)}
-	{
-	}
-};
-
-/* ------------------------------------------------------------------
- * Standard overloads for TypeInfo<T>
- * ------------------------------------------------------------------ */
-
-/**
- * @class TypeInfo<int>
- * @brief Default implementation for int.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeInfo<int> {
-public:
-	/**
-	 * Get an integer, return 0 if not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the integer
-	 */
-	static inline int get(Context &ctx, int index)
-	{
-		return duk_get_int(ctx, index);
-	}
-
-	/**
-	 * Check if value is an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if integer
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_number(ctx, index);
-	}
-
-	/**
-	 * Get an integer, return defaultValue if the value is not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the integer or defaultValue
-	 */
-	static inline int optional(Context &ctx, int index, int defaultValue)
-	{
-		if (!duk_is_number(ctx, index)) {
-			return defaultValue;
-		}
-
-		return duk_get_int(ctx, index);
-	}
-
-	/**
-	 * Push an integer.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, int value)
-	{
-		duk_push_int(ctx, value);
-	}
-
-	/**
-	 * Require an integer, throws a JavaScript exception if not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the integer
-	 */
-	static inline int require(Context &ctx, int index)
-	{
-		return duk_require_int(ctx, index);
-	}
-};
-
-/**
- * @class TypeInfo<bool>
- * @brief Default implementation for bool.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeInfo<bool> {
-public:
-	/**
-	 * Get a boolean, return 0 if not a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the boolean
-	 */
-	static inline bool get(Context &ctx, int index)
-	{
-		return duk_get_boolean(ctx, index);
-	}
-
-	/**
-	 * Check if value is a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if boolean
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_boolean(ctx, index);
-	}
-
-	/**
-	 * Get a bool, return defaultValue if the value is not a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the boolean or defaultValue
-	 */
-	static inline bool optional(Context &ctx, int index, bool defaultValue)
-	{
-		if (!duk_is_boolean(ctx, index)) {
-			return defaultValue;
-		}
-
-		return duk_get_boolean(ctx, index);
-	}
-
-	/**
-	 * Push a boolean.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, bool value)
-	{
-		duk_push_boolean(ctx, value);
-	}
-
-	/**
-	 * Require a boolean, throws a JavaScript exception if not a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the boolean
-	 */
-	static inline bool require(Context &ctx, int index)
-	{
-		return duk_require_boolean(ctx, index);
-	}
-};
-
-/**
- * @class TypeInfo<double>
- * @brief Default implementation for double.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeInfo<double> {
-public:
-	/**
-	 * Get a double, return 0 if not a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the double
-	 */
-	static inline double get(Context &ctx, int index)
-	{
-		return duk_get_number(ctx, index);
-	}
-
-	/**
-	 * Check if value is a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if double
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_number(ctx, index);
-	}
-
-	/**
-	 * Get a double, return defaultValue if the value is not a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the double or defaultValue
-	 */
-	static inline double optional(Context &ctx, int index, double defaultValue)
-	{
-		if (!duk_is_number(ctx, index)) {
-			return defaultValue;
-		}
-
-		return duk_get_number(ctx, index);
-	}
-
-	/**
-	 * Push a double.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, double value)
-	{
-		duk_push_number(ctx, value);
-	}
-
-	/**
-	 * Require a double, throws a JavaScript exception if not a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the double
-	 */
-	static inline double require(Context &ctx, int index)
-	{
-		return duk_require_number(ctx, index);
-	}
-};
-
-/**
- * @class TypeInfo<std::string>
- * @brief Default implementation for std::string.
- *
- * Provides: get, is, optional, push, require.
- *
- * Note: the functions allows embedded '\0'.
- */
-template <>
-class TypeInfo<std::string> {
-public:
-	/**
-	 * Get a string, return 0 if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline std::string get(Context &ctx, int index)
-	{
-		duk_size_t size;
-		const char *text = duk_get_lstring(ctx, index, &size);
-
-		return std::string{text, size};
-	}
-
-	/**
-	 * Check if value is a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if string
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_string(ctx, index);
-	}
-
-	/**
-	 * Get a string, return defaultValue if the value is not an string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the string or defaultValue
-	 */
-	static inline std::string optional(Context &ctx, int index, std::string defaultValue)
-	{
-		if (!duk_is_string(ctx, index)) {
-			return defaultValue;
-		}
-
-		return get(ctx, index);
-	}
-
-	/**
-	 * Push a string.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, const std::string &value)
-	{
-		duk_push_lstring(ctx, value.c_str(), value.length());
-	}
-
-	/**
-	 * Require a string, throws a JavaScript exception if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline std::string require(Context &ctx, int index)
-	{
-		duk_size_t size;
-		const char *text = duk_require_lstring(ctx, index, &size);
-
-		return std::string{text, size};
-	}
-};
-
-/**
- * @class TypeInfo<const char *>
- * @brief Default implementation for const char literals.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeInfo<const char *> {
-public:
-	/**
-	 * Get a string, return 0 if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline const char *get(Context &ctx, int index)
-	{
-		return duk_get_string(ctx, index);
-	}
-
-	/**
-	 * Check if value is a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if string
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_string(ctx, index);
-	}
-
-	/**
-	 * Get an integer, return defaultValue if the value is not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the integer or defaultValue
-	 */
-	static inline const char *optional(Context &ctx, int index, const char *defaultValue)
-	{
-		if (!duk_is_string(ctx, index)) {
-			return defaultValue;
-		}
-
-		return duk_get_string(ctx, index);
-	}
-
-	/**
-	 * Push a string.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, const char *value)
-	{
-		duk_push_string(ctx, value);
-	}
-
-	/**
-	 * Require a string, throws a JavaScript exception if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline const char *require(Context &ctx, int index)
-	{
-		return duk_require_string(ctx, index);
-	}
-};
-
-/**
- * @brief Implementation for non-managed pointers.
- *
- * Provides: get, is, optional, push, require.
- */
-template <typename T>
-class TypeInfo<RawPointer<T>> {
-public:
-	/**
-	 * Get a pointer, return nullptr if not a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the pointer
-	 */
-	static inline T *get(Context &ctx, int index)
-	{
-		return static_cast<T *>(duk_to_pointer(ctx, index));
-	}
-
-	/**
-	 * Check if value is a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if pointer
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_pointer(ctx, index);
-	}
-
-	/**
-	 * Get a pointer, return defaultValue if the value is not a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the pointer or defaultValue
-	 */
-	static inline T *optional(Context &ctx, int index, RawPointer<T> defaultValue)
-	{
-		if (!duk_is_pointer(ctx, index)) {
-			return defaultValue.object;
-		}
-
-		return static_cast<T *>(duk_to_pointer(ctx, index));
-	}
-
-	/**
-	 * Push a pointer.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(Context &ctx, const RawPointer<T> &value)
-	{
-		duk_push_pointer(ctx, value.object);
-	}
-
-	/**
-	 * Require a pointer, throws a JavaScript exception if not a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the pointer
-	 */
-	static inline T *require(Context &ctx, int index)
-	{
-		return static_cast<T *>(duk_require_pointer(ctx, index));
-	}
-};
-
-/**
- * @class TypeInfo<Function>
- * @brief Push C++ function to the stack.
- *
- * Provides: push.
- *
- * This implementation push a Duktape/C function that is wrapped as C++ for convenience.
- */
-template <>
-class TypeInfo<Function> {
-public:
-	/**
-	 * Push the C++ function, it is wrapped as Duktape/C function and allocated on the heap by moving the
-	 * std::function.
-	 *
-	 * @param ctx the context
-	 * @param fn the function
-	 */
-	static void push(Context &ctx, Function fn);
-};
-
-/**
- * @class TypeInfo<FunctionMap>
- * @brief Put the functions to the object at the top of the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeInfo<FunctionMap> {
-public:
-	/**
-	 * Push a map of function to the object at the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param map the map of function
-	 */
-	static inline void push(Context &ctx, const FunctionMap &map)
-	{
-		for (const auto &entry : map) {
-			ctx.putProperty(-1, entry.first, entry.second);
-		}
-	}
-};
-
-/**
- * @class TypeInfo<Object>
- * @brief Push empty object to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeInfo<Object> {
-public:
-	/**
-	 * Check if value is an object.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if object
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_object(ctx, index);
-	}
-
-	/**
-	 * Create an empty object on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const Object &)
-	{
-		duk_push_object(ctx);
-	}
-};
-
-/**
- * @class TypeInfo<Array>
- * @brief Push empty array to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeInfo<Array> {
-public:
-	/**
-	 * Check if value is a array.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if array
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_array(ctx, index);
-	}
-
-	/**
-	 * Create an empty array on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const Array &)
-	{
-		duk_push_array(ctx);
-	}
-};
-
-/**
- * @class TypeInfo<Undefined>
- * @brief Push undefined value to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeInfo<Undefined> {
-public:
-	/**
-	 * Check if value is undefined.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if undefined
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_undefined(ctx, index);
-	}
-
-	/**
-	 * Push undefined value on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const Undefined &)
-	{
-		duk_push_undefined(ctx);
-	}
-};
-
-/**
- * @class TypeInfo<Null>
- * @brief Push null value to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeInfo<Null> {
-public:
-	/**
-	 * Check if value is null.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if null
-	 */
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_null(ctx, index);
-	}
-
-	/**
-	 * Push null value on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const Null &)
-	{
-		duk_push_null(ctx);
-	}
-};
-
-/**
- * @brief Push this binding into the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeInfo<This> {
-public:
-	/**
-	 * Push this function into the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const This &)
-	{
-		duk_push_this(ctx);
-	}
-};
-
-/**
- * @class TypeInfo<Global>
- * @brief Push the global object to the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeInfo<Global> {
-public:
-	/**
-	 * Push the global object into the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(Context &ctx, const Global &)
-	{
-		duk_push_global_object(ctx);
-	}
-};
-
-/**
- * @brief Push a map of key-value pair as objects.
- *
- * Provides: push.
- *
- * This class is convenient for settings constants such as enums, string and such.
- */
-template <typename T>
-class TypeInfo<std::unordered_map<std::string, T>> {
-public:
-	/**
-	 * Put all values from the map as properties to the object at the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param map the values
-	 * @note You need an object at the top of the stack before calling this function
-	 */
-	static void push(Context &ctx, const std::unordered_map<std::string, T> &map)
-	{
-		for (const auto &pair : map) {
-			TypeInfo<T>::push(ctx, pair.second);
-			duk_put_prop_string(ctx, -2, pair.first.c_str());
-		}
-	}
-};
-
-/**
- * @brief Push or get vectors as JavaScript arrays.
- *
- * Provides: get, push.
- */
-template <typename T>
-class TypeInfo<std::vector<T>> {
-public:
-	/**
-	 * Get an array from the stack.
-	 *
-	 * @param ctx the context
-	 * @param index the array index
-	 * @return the array or empty array if the value is not an array
-	 */
-	static std::vector<T> get(Context &ctx, int index)
-	{
-		std::vector<T> result;
-
-		if (!duk_is_array(ctx, -1)) {
-			return result;
-		}
-
-		int total = duk_get_length(ctx, index);
-		for (int i = 0; i < total; ++i) {
-			result.push_back(ctx.getProperty<T>(index, i));
-		}
-
-		return result;
-	}
-
-	/**
-	 * Create an array with the specified values.
-	 *
-	 * @param ctx the context
-	 * @param array the values
-	 */
-	static void push(Context &ctx, const std::vector<T> &array)
-	{
-		duk_push_array(ctx);
-
-		int i = 0;
-		for (const auto &v : array) {
-			TypeInfo<T>::push(ctx, v);
-			duk_put_prop_index(ctx, -2, i++);
-		}
-	}
-};
-
-/**
- * @brief Implementation of managed shared_ptr
- * @see Shared
- */
-template <typename T>
-class TypeInfo<Shared<T>> {
-private:
-	static void apply(Context &ctx, std::shared_ptr<T> value)
-	{
-		duk_push_boolean(ctx, false);
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
-		duk_push_pointer(ctx, new std::shared_ptr<T>(value));
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-shared-ptr");
-		duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
-			duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-
-			if (duk_to_boolean(ctx, -1)) {
-				duk_push_boolean(ctx, true);
-				duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-				duk_get_prop_string(ctx, 0, "\xff""\xff""js-shared-ptr");
-				delete static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
-				duk_pop(ctx);
-			}
-
-			duk_pop(ctx);
-
-			return 0;
-		}, 1);
-		duk_set_finalizer(ctx, -2);
-	}
-
-public:
-	/**
-	 * Construct the shared_ptr as this.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void construct(Context &ctx, Shared<T> value)
-	{
-		duk_push_this(ctx);
-		apply(ctx, std::move(value.object));
-		duk_pop(ctx);
-	}
-
-	/**
-	 * Push a managed shared_ptr as object.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void push(Context &ctx, Shared<T> value)
-	{
-		duk_push_object(ctx);
-		apply(ctx, value.object);
-		value.object->prototype(ctx);
-		duk_set_prototype(ctx, -2);
-	}
-
-	/**
-	 * Get a managed shared_ptr from the stack.
-	 *
-	 * @param ctx the context
-	 * @param index the object index
-	 * @return the shared_ptr
-	 */
-	static std::shared_ptr<T> get(Context &ctx, int 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 TypeInfo<Pointer<T>> {
-private:
-	static void apply(Context &ctx, T *value)
-	{
-		duk_push_boolean(ctx, false);
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
-		duk_push_pointer(ctx, value);
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-ptr");
-		duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
-			duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-
-			if (duk_to_boolean(ctx, -1)) {
-				duk_push_boolean(ctx, true);
-				duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
-				duk_get_prop_string(ctx, 0, "\xff""\xff""js-ptr");
-				delete static_cast<T *>(duk_to_pointer(ctx, -1));
-				duk_pop(ctx);
-			}
-
-			duk_pop(ctx);
-
-			return 0;
-		}, 1);
-		duk_set_finalizer(ctx, -2);
-	}
-
-public:
-	/**
-	 * Construct the pointer as this.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void construct(Context &ctx, Pointer<T> value)
-	{
-		duk_push_this(ctx);
-		apply(ctx, value.object);
-		duk_pop(ctx);
-	}
-
-	/**
-	 * Push a managed pointer as object.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void push(Context &ctx, Pointer<T> value)
-	{
-		duk_push_object(ctx);
-		apply(ctx, value.object);
-		value.object->prototype(ctx);
-		duk_set_prototype(ctx, -2);
-	}
-
-	/**
-	 * 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(Context &ctx, int index)
-	{
-		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;
-	}
-};
-
-} // !js
-
-#endif // !_JS_H_
+/*
+ * Js.h -- JavaScript C++14 wrapper for Duktape
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _JS_H_
+#define _JS_H_
+
+/**
+ * @file Js.h
+ * @brief Bring JavaScript using Duktape
+ *
+ * This file provides usual Duktape function renamed and placed into `js` namespace. It also replaces error
+ * code with exceptions when possible.
+ *
+ * For convenience, this file also provides templated functions, overloads and much more.
+ */
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <duktape.h>
+
+/**
+ * Duktape C++ namespace wrapper.
+ */
+namespace js {
+
+class Context;
+
+/**
+ * Typedef for readability.
+ */
+using ContextPtr = duk_context *;
+
+/*
+ * Basic types to manipulate with the stack
+ * ------------------------------------------------------------------
+ *
+ * The following types can be used in some of the operations like Context::push or Context::is, they are defined
+ * usually as empty classes to determine the appropriate action to execute.
+ *
+ * For example, `ctx.push(js::Object{})` will push an empty object into the stack.
+ */
+
+/**
+ * @class Object
+ * @brief Empty class tag for push() function.
+ */
+class Object {
+};
+
+/**
+ * @class Array
+ * @brief Empty class tag for push() function.
+ */
+class Array {
+};
+
+/**
+ * @class Global
+ * @brief Empty class tag to push the global object.
+ */
+class Global {
+};
+
+/**
+ * @class Undefined
+ * @brief Empty class tag to push undefined to the stack.
+ */
+class Undefined {
+};
+
+/**
+ * @class Null
+ * @brief Empty class tag to push null to the stack.
+ */
+class Null {
+};
+
+/**
+ * @class This
+ * @brief Empty class tag to push this binding to the stack.
+ */
+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;
+};
+
+/*
+ * Extended type manipulation
+ * ------------------------------------------------------------------
+ *
+ * The following types are different as there are no equivalent in the native Duktape API, they are available for
+ * convenience.
+ */
+
+/**
+ * @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.
+ *
+ * The only requirement is to have the function `void prototype(Context &ctx)` in your class T.
+ */
+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.
+ *
+ * This class wraps the std::function as a Duktape/C function by storing a copied pointer.
+ */
+class Function {
+public:
+	/**
+	 * The function pointer, must not be null.
+	 */
+	std::function<int (Context &)> function;
+
+	/**
+	 * Number of args that the function takes
+	 */
+	int nargs{0};
+};
+
+/**
+ * Map of functions to set on an object.
+ */
+using FunctionMap = std::unordered_map<std::string, Function>;
+
+/**
+ * Map of string to type, ideal for setting constants like enums.
+ */
+template <typename Type>
+using Map = std::unordered_map<std::string, Type>;
+
+/**
+ * @class ErrorInfo
+ * @brief Error description.
+ *
+ * This class fills the fields got in an Error object.
+ */
+class ErrorInfo : public std::exception {
+public:
+	std::string name;		//!< name of error
+	std::string message;		//!< error message
+	std::string stack;		//!< stack if available
+	std::string fileName;		//!< filename if applicable
+	int lineNumber{0};		//!< line number if applicable
+
+	/**
+	 * Get the error message. This effectively returns message field.
+	 *
+	 * @return the message
+	 */
+	const char *what() const noexcept override
+	{
+		return message.c_str();
+	}
+};
+
+/**
+ * @class TypeInfo
+ * @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 TypeInfo {
+};
+
+/**
+ * @class File
+ * @brief Evaluate script from file.
+ * @see Context::eval
+ * @see Context::peval
+ */
+class File {
+public:
+	/**
+	 * Path to the file.
+	 */
+	std::string path;
+
+	/**
+	 * Evaluate the file.
+	 *
+	 * @param ctx the context
+	 */
+	inline void eval(duk_context *ctx)
+	{
+		duk_eval_file(ctx, path.c_str());
+	}
+
+	/**
+	 * Evaluate in protected mode the file.
+	 *
+	 * @param ctx the context
+	 */
+	inline int peval(duk_context *ctx)
+	{
+		return duk_peval_file(ctx, path.c_str());
+	}
+};
+
+/**
+ * @class Script
+ * @brief Evaluate script from raw text.
+ * @see Context::eval
+ * @see Context::peval
+ */
+class Script {
+public:
+	/**
+	 * The script content.
+	 */
+	std::string text;
+
+	/**
+	 * Evaluate the script.
+	 *
+	 * @param ctx the context
+	 */
+	inline void eval(duk_context *ctx)
+	{
+		duk_eval_string(ctx, text.c_str());
+	}
+
+	/**
+	 * Evaluate in protected mode the script.
+	 *
+	 * @param ctx the context
+	 */
+	inline int peval(duk_context *ctx)
+	{
+		return duk_peval_string(ctx, text.c_str());
+	}
+};
+
+/**
+ * @class Context
+ * @brief RAII based Duktape handler.
+ *
+ * This class is implicitly convertible to duk_context for convenience.
+ */
+class Context {
+private:
+	using Deleter = void (*)(duk_context *);
+	using Handle = std::unique_ptr<duk_context, Deleter>;
+
+	Handle m_handle;
+
+	/* Move and copy forbidden */
+	Context(const Context &) = delete;
+	Context &operator=(const Context &) = delete;
+	Context(const Context &&) = delete;
+	Context &operator=(const Context &&) = delete;
+
+public:
+	/**
+	 * Create default context.
+	 */
+	inline Context()
+		: m_handle{duk_create_heap_default(), duk_destroy_heap}
+	{
+	}
+
+	/**
+	 * Create borrowed context that will not be deleted.
+	 *
+	 * @param ctx the pointer to duk_context
+	 */
+	inline Context(ContextPtr ctx) noexcept
+		: m_handle{ctx, [] (ContextPtr) {}}
+	{
+	}
+
+	/**
+	 * Convert the context to the native Duktape/C type.
+	 *
+	 * @return the duk_context
+	 */
+	inline operator duk_context *() noexcept
+	{
+		return m_handle.get();
+	}
+
+	/**
+	 * Convert the context to the native Duktape/C type.
+	 *
+	 * @return the duk_context
+	 */
+	inline operator duk_context *() const noexcept
+	{
+		return m_handle.get();
+	}
+
+	/*
+	 * Basic functions
+	 * ----------------------------------------------------------
+	 *
+	 * The following functions are just standard wrappers around the native Duktape C functions, they are
+	 * defined with the same signature except that for convenience some parameters have default sane values.
+	 */
+
+	/**
+	 * Call the object at the top of the stack.
+	 *
+	 * @param ctx the context
+	 * @param nargs the number of arguments
+	 * @note Non-protected
+	 */
+	inline void call(unsigned nargs = 0)
+	{
+		duk_call(m_handle.get(), nargs);
+	}
+
+	/**
+	 * Copy a value from from to to, overwriting the previous value. If either index is invalid, throws an error.
+	 *
+	 * @param from the from index
+	 * @param to the destination
+	 */
+	inline void copy(int from, int to)
+	{
+		duk_copy(m_handle.get(), from, to);
+	}
+
+	/**
+	 * Define a property.
+	 *
+	 * @param index the object index
+	 * @param flags the flags
+	 * @note Wrapper of duk_def_prop
+	 */
+	inline void defineProperty(int index, int flags)
+	{
+		duk_def_prop(m_handle.get(), index, flags);
+	}
+
+	/**
+	 * Delete a property.
+	 *
+	 * @param index the object index
+	 * @return true if deleted
+	 * @note Wrapper of duk_del_prop
+	 */
+	inline bool deleteProperty(int index)
+	{
+		return duk_del_prop(m_handle.get(), index);
+	}
+
+	/**
+	 * Delete a property by index.
+	 *
+	 * @param index the object index
+	 * @param position the property index
+	 * @return true if deleted
+	 * @note Wrapper of duk_del_prop_index
+	 */
+	inline bool deleteProperty(int index, int position)
+	{
+		return duk_del_prop_index(m_handle.get(), index, position);
+	}
+
+	/**
+	 * Delete a property by name.
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @return true if deleted
+	 * @note Wrapper of duk_del_prop_string
+	 */
+	inline bool deleteProperty(int index, const std::string &name)
+	{
+		return duk_del_prop_string(m_handle.get(), index, name.c_str());
+	}
+
+	/**
+	 * Push a duplicate of value at from_index to the stack. If from_index is invalid, throws an error.
+	 *
+	 * @param index the value to copy
+	 * @note Wrapper of duk_dup
+	 */
+	inline void dup(int index = -1)
+	{
+		duk_dup(m_handle.get(), index);
+	}
+
+	/**
+	 * Evaluate a non-protected chunk that is at the top of the stack.
+	 */
+	inline void eval()
+	{
+		duk_eval(m_handle.get());
+	}
+
+	/**
+	 * Check if the object as a property.
+	 *
+	 * @param index the object index
+	 * @return true if has
+	 * @note Wrapper of duk_has_prop
+	 */
+	inline bool hasProperty(int index)
+	{
+		return duk_has_prop(m_handle.get(), index);
+	}
+
+	/**
+	 * Check if the object as a property by index.
+	 *
+	 * @param index the object index
+	 * @param position the property index
+	 * @return true if has
+	 * @note Wrapper of duk_has_prop_index
+	 */
+	inline bool hasProperty(int index, int position)
+	{
+		return duk_has_prop_index(m_handle.get(), index, position);
+	}
+
+	/**
+	 * Check if the object as a property by string
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @return true if has
+	 * @note Wrapper of duk_has_prop_string
+	 */
+	inline bool hasProperty(int index, const std::string &name)
+	{
+		return duk_has_prop_string(m_handle.get(), index, name.c_str());
+	}
+
+	/**
+	 * Check if idx1 is an instance of idx2.
+	 *
+	 * @param ctx the context
+	 * @param idx1 the value to test
+	 * @param idx2 the instance requested
+	 * @return true if idx1 is instance of idx2
+	 * @note Wrapper of duk_instanceof
+	 */
+	inline bool instanceof(int idx1, int idx2)
+	{
+		return duk_instanceof(m_handle.get(), idx1, idx2);
+	}
+
+	/**
+	 * Insert a value at to with a value popped from the stack top. The previous value at to and any values above
+	 * it are moved up the stack by a step. If to is an invalid index, throws an error.
+	 *
+	 * @note Negative indices are evaluated prior to popping the value at the stack top
+	 * @param to the destination
+	 * @note Wrapper of duk_insert
+	 */
+	inline void insert(int to)
+	{
+		duk_insert(m_handle.get(), to);
+	}
+
+	/**
+	 * Pop a certain number of values from the top of the stack.
+	 *
+	 * @param ctx the context
+	 * @param count the number of values to pop
+	 * @note Wrapper of duk_pop_n
+	 */
+	inline void pop(unsigned count = 1)
+	{
+		duk_pop_n(m_handle.get(), count);
+	}
+
+	/**
+	 * Remove value at index. Elements above index are shifted down the stack by a step. If to is an invalid index,
+	 * throws an error.
+	 *
+	 * @param index the value to remove
+	 * @note Wrapper of duk_remove
+	 */
+	inline void remove(int index)
+	{
+		duk_remove(m_handle.get(), index);
+	}
+
+	/**
+	 * Replace value at to_index with a value popped from the stack top. If to_index is an invalid index,
+	 * throws an error.
+	 *
+	 * @param index the value to replace by the value at the top of the stack
+	 * @note Negative indices are evaluated prior to popping the value at the stack top.
+	 * @note Wrapper of duk_replace
+	 */
+	inline void replace(int index)
+	{
+		duk_replace(m_handle.get(), index);
+	}
+
+	/**
+	 * Swap values at indices index1 and index2. If the indices are the same, the call is a no-op. If either index
+	 * is invalid, throws an error.
+	 *
+	 * @param index1 the first index
+	 * @param index2 the second index
+	 * @note Wrapper of duk_swap
+	 */
+	inline void swap(int index1, int index2)
+	{
+		duk_swap(m_handle.get(), index1, index2);
+	}
+
+	/**
+	 * Get the current stack size.
+	 *
+	 * @param ctx the context
+	 * @return the stack size
+	 * @note Wrapper of duk_get_top
+	 */
+	inline int top() noexcept
+	{
+		return duk_get_top(m_handle.get());
+	}
+
+	/**
+	 * Get the type of the value at the specified index.
+	 *
+	 * @param ctx the context
+	 * @param index the idnex
+	 * @return the type
+	 * @note Wrapper of duk_get_type
+	 */
+	inline int type(int index) noexcept
+	{
+		return duk_get_type(m_handle.get(), index);
+	}
+
+	/*
+	 * Extended native functions
+	 * ----------------------------------------------------------
+	 *
+	 * The following functions have different behaviour than the original native Duktape C functions, see their
+	 * descriptions for more information
+	 */
+
+	/**
+	 * Call in protected mode the object at the top of the stack.
+	 *
+	 * @param nargs the number of arguments
+	 * @throw ErrorInfo on errors
+	 * @note Wrapper of duk_pcall
+	 */
+	void pcall(unsigned nargs = 0);
+
+	/**
+	 * Evaluate a non-protected source.
+	 *
+	 * @param source the source
+	 * @see File
+	 * @see Script
+	 * @note Wrapper of duk_eval
+	 */
+	template <typename Source>
+	inline void eval(Source &&source)
+	{
+		source.eval(m_handle.get());
+	}
+
+	/**
+	 * Evaluate a protected chunk that is at the top of the stack.
+	 *
+	 * @throw ErrorInfo the error
+	 * @note Wrapper of duk_peval
+	 */
+	void peval();
+
+	/**
+	 * Evaluate a protected source.
+	 *
+	 * @param source the source
+	 * @see File
+	 * @see Script
+	 * @throw ErrorInfo on failure
+	 * @note Wrapper of duk_peval
+	 */
+	template <typename Source>
+	inline void peval(Source &&source)
+	{
+		if (source.peval(m_handle.get()) != 0) {
+			ErrorInfo info = error(-1);
+			duk_pop(m_handle.get());
+
+			throw info;
+		}
+	}
+
+	/*
+	 * Push / Get / Require / Is / Optional
+	 * ----------------------------------------------------------
+	 *
+	 * The following functions are used to push, get or check values from the stack. They use specialization
+	 * of TypeInfo class.
+	 */
+
+	/**
+	 * Push a value into the stack. Calls TypeInfo<T>::push(*this, value);
+	 *
+	 * @param value the value to forward
+	 */
+	template <typename Type>
+	inline void push(Type &&value)
+	{
+		TypeInfo<std::decay_t<Type>>::push(*this, std::forward<Type>(value));
+	}
+
+	/**
+	 * Generic template function to get a value from the stack.
+	 *
+	 * @param index the index
+	 * @return the value
+	 */
+	template <typename Type>
+	inline auto get(int index) -> decltype(TypeInfo<Type>::get(*this, 0))
+	{
+		return TypeInfo<Type>::get(*this, index);
+	}
+
+	/**
+	 * Require a type at the specified index.
+	 *
+	 * @param index the index
+	 * @return the value
+	 */
+	template <typename Type>
+	inline auto require(int index) -> decltype(TypeInfo<Type>::require(*this, 0))
+	{
+		return TypeInfo<Type>::require(*this, index);
+	}
+
+	/**
+	 * Check if a value is a type of T.
+	 *
+	 * The TypeInfo<T> must have `static bool is(ContextPtr ptr, int index)`.
+	 *
+	 * @param index the value index
+	 * @return true if is the type
+	 */
+	template <typename T>
+	inline bool is(int index)
+	{
+		return TypeInfo<T>::is(*this, index);
+	}
+
+	/**
+	 * Get an optional value from the stack, if the value is not available of not the correct type,
+	 * return defaultValue instead.
+	 *
+	 * The TypeInfo<T> must have `static T optional(Context &, int index, T &&defaultValue)`.
+	 *
+	 * @param index the value index
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename Type>
+	inline auto optional(int index, Type &&defaultValue)
+	{
+		return TypeInfo<std::decay_t<Type>>::optional(*this, index, std::forward<Type>(defaultValue));
+	}
+
+	/*
+	 * Properties management
+	 * ----------------------------------------------------------
+	 *
+	 * The following functions are used to read or set properties on objects or globals also using TypeInfo.
+	 */
+
+	/**
+	 * Get the property `name' as value from the object at the specified index.
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @return the value
+	 * @note The stack is unchanged
+	 */
+	template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
+	inline auto getProperty(int index, const std::string &name) -> decltype(get<Type>(0))
+	{
+		duk_get_prop_string(m_handle.get(), index, name.c_str());
+		decltype(get<Type>(0)) value = get<Type>(-1);
+		duk_pop(m_handle.get());
+
+		return value;
+	}
+
+	/**
+	 * Get a property by index, for arrays.
+	 *
+	 * @param index the object index
+	 * @param position the position int the object
+	 * @return the value
+	 * @note The stack is unchanged
+	 */
+	template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
+	inline auto getProperty(int index, int position) -> decltype(get<Type>(0))
+	{
+		duk_get_prop_index(m_handle.get(), index, position);
+		decltype(get<Type>(0)) value = get<Type>(-1);
+		duk_pop(m_handle.get());
+
+		return value;
+	}
+
+	/**
+	 * Get the property `name' and push it to the stack from the object at the specified index.
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @note The stack contains the property value
+	 */
+	template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
+	inline void getProperty(int index, const std::string &name)
+	{
+		duk_get_prop_string(m_handle.get(), index, name.c_str());
+	}
+
+	/**
+	 * Get the property by index and push it to the stack from the object at the specified index.
+	 *
+	 * @param index the object index
+	 * @param position the position in the object
+	 * @note The stack contains the property value
+	 */
+	template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
+	inline void getProperty(int index, int position)
+	{
+		duk_get_prop_index(m_handle.get(), index, position);
+	}
+
+	/**
+	 * Set a property to the object at the specified index.
+	 *
+	 * @param index the object index
+	 * @param name the property name
+	 * @param value the value to forward
+	 * @note The stack is unchanged
+	 */
+	template <typename Type>
+	void putProperty(int index, const std::string &name, Type &&value)
+	{
+		index = duk_normalize_index(m_handle.get(), index);
+
+		push(std::forward<Type>(value));
+		duk_put_prop_string(m_handle.get(), index, name.c_str());
+	}
+
+	/**
+	 * Set a property by index, for arrays.
+	 *
+	 * @param index the object index
+	 * @param position the position in the object
+	 * @param value the value to forward
+	 * @note The stack is unchanged
+	 */
+	template <typename Type>
+	void putProperty(int index, int position, Type &&value)
+	{
+		index = duk_normalize_index(m_handle.get(), index);
+
+		push(std::forward<Type>(value));
+		duk_put_prop_index(m_handle.get(), index, position);
+	}
+
+	/**
+	 * 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(int index, const std::string &name)
+	{
+		duk_put_prop_string(m_handle.get(), 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(int index, int position)
+	{
+		duk_put_prop_index(m_handle.get(), index, position);
+	}
+
+	/**
+	 * Get a global value.
+	 *
+	 * @param name the name of the global variable
+	 * @return the value
+	 */
+	template <typename Type>
+	inline auto getGlobal(const std::string &name, std::enable_if_t<!std::is_void<Type>::value> * = nullptr) -> decltype(get<Type>(0))
+	{
+		duk_get_global_string(m_handle.get(), name.c_str());
+		decltype(get<Type>(0)) value = get<Type>(-1);
+		duk_pop(m_handle.get());
+
+		return value;
+	}
+
+	/**
+	 * Overload that push the value at the top of the stack instead of returning it.
+	 */
+	template <typename Type>
+	inline void getGlobal(const std::string &name, std::enable_if_t<std::is_void<Type>::value> * = nullptr) noexcept
+	{
+		duk_get_global_string(m_handle.get(), name.c_str());
+	}
+
+	/**
+	 * Set a global variable.
+	 *
+	 * @param name the name of the global variable
+	 * @param type the value to set
+	 */
+	template <typename Type>
+	inline void putGlobal(const std::string &name, Type&& type)
+	{
+		push(std::forward<Type>(type));
+		duk_put_global_string(m_handle.get(), name.c_str());
+	}
+
+	/**
+	 * Put the value at the top of the stack as global property.
+	 *
+	 * @param name the property name
+	 */
+	inline void putGlobal(const std::string &name)
+	{
+		duk_put_global_string(m_handle.get(), name.c_str());
+	}
+
+	/*
+	 * Extra functions
+	 * ----------------------------------------------------------
+	 *
+	 * The following functions are implemented for convenience and do not exists in the native Duktape API.
+	 */
+
+	/**
+	 * Get the error object when a JavaScript error has been thrown (e.g. eval failure).
+	 *
+	 * @param index the index
+	 * @return the information
+	 */
+	ErrorInfo error(int index);
+
+	/**
+	 * Enumerate an object or an array at the specified index.
+	 *
+	 * @param index the object or array index
+	 * @param flags the optional flags to pass to duk_enum
+	 * @param getvalue set to true if you want to extract the value
+	 * @param func the function to call for each properties
+	 */
+	template <typename Func>
+	void enumerate(int index, duk_uint_t flags, duk_bool_t getvalue, Func&& func)
+	{
+		duk_enum(m_handle.get(), index, flags);
+
+		while (duk_next(m_handle.get(), -1, getvalue)) {
+			func(*this);
+			duk_pop_n(m_handle.get(), 1 + (getvalue ? 1 : 0));
+		}
+
+		duk_pop(m_handle.get());
+	}
+
+	/**
+	 * Return the this binding of the current function.
+	 *
+	 * @return the this binding as the template given
+	 */
+	template <typename T>
+	inline auto self() -> decltype(TypeInfo<T>::get(*this, 0))
+	{
+		duk_push_this(m_handle.get());
+		decltype(TypeInfo<T>::get(*this, 0)) value = TypeInfo<T>::get(*this, -1);
+		duk_pop(m_handle.get());
+
+		return value;
+	}
+
+	/**
+	 * Throw an ECMAScript exception.
+	 *
+	 * @param ex the exception
+	 */
+	template <typename Exception>
+	void raise(const Exception &ex)
+	{
+		ex.create(m_handle.get());
+
+		duk_push_string(m_handle.get(), ex.name().c_str());
+		duk_put_prop_string(m_handle.get(), -2, "name");
+		duk_throw(m_handle.get());
+	}
+
+	/**
+	 * Construct the object in place, setting value as this binding.
+	 *
+	 * The TypeInfo<T> must have the following requirements:
+	 *
+	 * - static void construct(Context &, T): must update this with the value and keep the stack unchanged
+	 *
+	 * @param value the value to forward
+	 * @see self
+	 */
+	template <typename T>
+	inline void construct(T &&value)
+	{
+		TypeInfo<std::decay_t<T>>::construct(*this, std::forward<T>(value));
+	}
+};
+
+/* ------------------------------------------------------------------
+ * Exception handling
+ * ------------------------------------------------------------------ */
+
+/**
+ * @class Error
+ * @brief Base ECMAScript error class.
+ * @warning Override the function create for your own exceptions
+ */
+class Error {
+protected:
+	std::string m_name;	//!< Name of exception (e.g RangeError)
+	std::string m_message;	//!< The message
+
+	/**
+	 * Constructor with a type of error specified, specially designed for derived errors.
+	 *
+	 * @param name the error name (e.g RangeError)
+	 * @param message the message
+	 */
+	inline Error(std::string name, std::string message) noexcept
+		: m_name{std::move(name)}
+		, m_message{std::move(message)}
+	{
+	}
+
+public:
+	/**
+	 * Constructor with a message.
+	 *
+	 * @param message the message
+	 */
+	inline Error(std::string message) noexcept
+		: m_name{"Error"}
+		, m_message{std::move(message)}
+	{
+	}
+
+	/**
+	 * Get the error type (e.g RangeError).
+	 *
+	 * @return the name
+	 */
+	inline const std::string &name() const noexcept
+	{
+		return m_name;
+	}
+
+	/**
+	 * Create the exception on the stack.
+	 *
+	 * @note the default implementation search for the global variables
+	 * @param ctx the context
+	 */
+	virtual void create(ContextPtr ctx) const noexcept
+	{
+		duk_get_global_string(ctx, m_name.c_str());
+		duk_push_string(ctx, m_message.c_str());
+		duk_new(ctx, 1);
+	}
+};
+
+/**
+ * @class EvalError
+ * @brief Error in eval() function.
+ */
+class EvalError : public Error {
+public:
+	/**
+	 * Construct an EvalError.
+	 *
+	 * @param message the message
+	 */
+	inline EvalError(std::string message) noexcept
+		: Error{"EvalError", std::move(message)}
+	{
+	}
+};
+
+/**
+ * @class RangeError
+ * @brief Value is out of range.
+ */
+class RangeError : public Error {
+public:
+	/**
+	 * Construct an RangeError.
+	 *
+	 * @param message the message
+	 */
+	inline RangeError(std::string message) noexcept
+		: Error{"RangeError", std::move(message)}
+	{
+	}
+};
+
+/**
+ * @class ReferenceError
+ * @brief Trying to use a variable that does not exist.
+ */
+class ReferenceError : public Error {
+public:
+	/**
+	 * Construct an ReferenceError.
+	 *
+	 * @param message the message
+	 */
+	inline ReferenceError(std::string message) noexcept
+		: Error{"ReferenceError", std::move(message)}
+	{
+	}
+};
+
+/**
+ * @class SyntaxError
+ * @brief Syntax error in the script.
+ */
+class SyntaxError : public Error {
+public:
+	/**
+	 * Construct an SyntaxError.
+	 *
+	 * @param message the message
+	 */
+	inline SyntaxError(std::string message) noexcept
+		: Error{"SyntaxError", std::move(message)}
+	{
+	}
+};
+
+/**
+ * @class TypeError
+ * @brief Invalid type given.
+ */
+class TypeError : public Error {
+public:
+	/**
+	 * Construct an TypeError.
+	 *
+	 * @param message the message
+	 */
+	inline TypeError(std::string message) noexcept
+		: Error{"TypeError", std::move(message)}
+	{
+	}
+};
+
+/**
+ * @class URIError
+ * @brief URI manipulation failure.
+ */
+class URIError : public Error {
+public:
+	/**
+	 * Construct an URIError.
+	 *
+	 * @param message the message
+	 */
+	inline URIError(std::string message) noexcept
+		: Error{"URIError", std::move(message)}
+	{
+	}
+};
+
+/* ------------------------------------------------------------------
+ * Standard overloads for TypeInfo<T>
+ * ------------------------------------------------------------------ */
+
+/**
+ * @class TypeInfo<int>
+ * @brief Default implementation for int.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeInfo<int> {
+public:
+	/**
+	 * Get an integer, return 0 if not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the integer
+	 */
+	static inline int get(Context &ctx, int index)
+	{
+		return duk_get_int(ctx, index);
+	}
+
+	/**
+	 * Check if value is an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if integer
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_number(ctx, index);
+	}
+
+	/**
+	 * Get an integer, return defaultValue if the value is not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the integer or defaultValue
+	 */
+	static inline int optional(Context &ctx, int index, int defaultValue)
+	{
+		if (!duk_is_number(ctx, index)) {
+			return defaultValue;
+		}
+
+		return duk_get_int(ctx, index);
+	}
+
+	/**
+	 * Push an integer.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, int value)
+	{
+		duk_push_int(ctx, value);
+	}
+
+	/**
+	 * Require an integer, throws a JavaScript exception if not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the integer
+	 */
+	static inline int require(Context &ctx, int index)
+	{
+		return duk_require_int(ctx, index);
+	}
+};
+
+/**
+ * @class TypeInfo<bool>
+ * @brief Default implementation for bool.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeInfo<bool> {
+public:
+	/**
+	 * Get a boolean, return 0 if not a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the boolean
+	 */
+	static inline bool get(Context &ctx, int index)
+	{
+		return duk_get_boolean(ctx, index);
+	}
+
+	/**
+	 * Check if value is a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if boolean
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_boolean(ctx, index);
+	}
+
+	/**
+	 * Get a bool, return defaultValue if the value is not a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the boolean or defaultValue
+	 */
+	static inline bool optional(Context &ctx, int index, bool defaultValue)
+	{
+		if (!duk_is_boolean(ctx, index)) {
+			return defaultValue;
+		}
+
+		return duk_get_boolean(ctx, index);
+	}
+
+	/**
+	 * Push a boolean.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, bool value)
+	{
+		duk_push_boolean(ctx, value);
+	}
+
+	/**
+	 * Require a boolean, throws a JavaScript exception if not a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the boolean
+	 */
+	static inline bool require(Context &ctx, int index)
+	{
+		return duk_require_boolean(ctx, index);
+	}
+};
+
+/**
+ * @class TypeInfo<double>
+ * @brief Default implementation for double.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeInfo<double> {
+public:
+	/**
+	 * Get a double, return 0 if not a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the double
+	 */
+	static inline double get(Context &ctx, int index)
+	{
+		return duk_get_number(ctx, index);
+	}
+
+	/**
+	 * Check if value is a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if double
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_number(ctx, index);
+	}
+
+	/**
+	 * Get a double, return defaultValue if the value is not a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the double or defaultValue
+	 */
+	static inline double optional(Context &ctx, int index, double defaultValue)
+	{
+		if (!duk_is_number(ctx, index)) {
+			return defaultValue;
+		}
+
+		return duk_get_number(ctx, index);
+	}
+
+	/**
+	 * Push a double.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, double value)
+	{
+		duk_push_number(ctx, value);
+	}
+
+	/**
+	 * Require a double, throws a JavaScript exception if not a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the double
+	 */
+	static inline double require(Context &ctx, int index)
+	{
+		return duk_require_number(ctx, index);
+	}
+};
+
+/**
+ * @class TypeInfo<std::string>
+ * @brief Default implementation for std::string.
+ *
+ * Provides: get, is, optional, push, require.
+ *
+ * Note: the functions allows embedded '\0'.
+ */
+template <>
+class TypeInfo<std::string> {
+public:
+	/**
+	 * Get a string, return 0 if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline std::string get(Context &ctx, int index)
+	{
+		duk_size_t size;
+		const char *text = duk_get_lstring(ctx, index, &size);
+
+		return std::string{text, size};
+	}
+
+	/**
+	 * Check if value is a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if string
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_string(ctx, index);
+	}
+
+	/**
+	 * Get a string, return defaultValue if the value is not an string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the string or defaultValue
+	 */
+	static inline std::string optional(Context &ctx, int index, std::string defaultValue)
+	{
+		if (!duk_is_string(ctx, index)) {
+			return defaultValue;
+		}
+
+		return get(ctx, index);
+	}
+
+	/**
+	 * Push a string.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, const std::string &value)
+	{
+		duk_push_lstring(ctx, value.c_str(), value.length());
+	}
+
+	/**
+	 * Require a string, throws a JavaScript exception if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline std::string require(Context &ctx, int index)
+	{
+		duk_size_t size;
+		const char *text = duk_require_lstring(ctx, index, &size);
+
+		return std::string{text, size};
+	}
+};
+
+/**
+ * @class TypeInfo<const char *>
+ * @brief Default implementation for const char literals.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeInfo<const char *> {
+public:
+	/**
+	 * Get a string, return 0 if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline const char *get(Context &ctx, int index)
+	{
+		return duk_get_string(ctx, index);
+	}
+
+	/**
+	 * Check if value is a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if string
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_string(ctx, index);
+	}
+
+	/**
+	 * Get an integer, return defaultValue if the value is not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the integer or defaultValue
+	 */
+	static inline const char *optional(Context &ctx, int index, const char *defaultValue)
+	{
+		if (!duk_is_string(ctx, index)) {
+			return defaultValue;
+		}
+
+		return duk_get_string(ctx, index);
+	}
+
+	/**
+	 * Push a string.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, const char *value)
+	{
+		duk_push_string(ctx, value);
+	}
+
+	/**
+	 * Require a string, throws a JavaScript exception if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline const char *require(Context &ctx, int index)
+	{
+		return duk_require_string(ctx, index);
+	}
+};
+
+/**
+ * @brief Implementation for non-managed pointers.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <typename T>
+class TypeInfo<RawPointer<T>> {
+public:
+	/**
+	 * Get a pointer, return nullptr if not a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the pointer
+	 */
+	static inline T *get(Context &ctx, int index)
+	{
+		return static_cast<T *>(duk_to_pointer(ctx, index));
+	}
+
+	/**
+	 * Check if value is a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if pointer
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_pointer(ctx, index);
+	}
+
+	/**
+	 * Get a pointer, return defaultValue if the value is not a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the pointer or defaultValue
+	 */
+	static inline T *optional(Context &ctx, int index, RawPointer<T> defaultValue)
+	{
+		if (!duk_is_pointer(ctx, index)) {
+			return defaultValue.object;
+		}
+
+		return static_cast<T *>(duk_to_pointer(ctx, index));
+	}
+
+	/**
+	 * Push a pointer.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(Context &ctx, const RawPointer<T> &value)
+	{
+		duk_push_pointer(ctx, value.object);
+	}
+
+	/**
+	 * Require a pointer, throws a JavaScript exception if not a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the pointer
+	 */
+	static inline T *require(Context &ctx, int index)
+	{
+		return static_cast<T *>(duk_require_pointer(ctx, index));
+	}
+};
+
+/**
+ * @class TypeInfo<Function>
+ * @brief Push C++ function to the stack.
+ *
+ * Provides: push.
+ *
+ * This implementation push a Duktape/C function that is wrapped as C++ for convenience.
+ */
+template <>
+class TypeInfo<Function> {
+public:
+	/**
+	 * Push the C++ function, it is wrapped as Duktape/C function and allocated on the heap by moving the
+	 * std::function.
+	 *
+	 * @param ctx the context
+	 * @param fn the function
+	 */
+	static void push(Context &ctx, Function fn);
+};
+
+/**
+ * @class TypeInfo<FunctionMap>
+ * @brief Put the functions to the object at the top of the stack.
+ *
+ * Provides: push.
+ */
+template <>
+class TypeInfo<FunctionMap> {
+public:
+	/**
+	 * Push a map of function to the object at the top of the stack.
+	 *
+	 * @param ctx the context
+	 * @param map the map of function
+	 */
+	static inline void push(Context &ctx, const FunctionMap &map)
+	{
+		for (const auto &entry : map) {
+			ctx.putProperty(-1, entry.first, entry.second);
+		}
+	}
+};
+
+/**
+ * @class TypeInfo<Object>
+ * @brief Push empty object to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeInfo<Object> {
+public:
+	/**
+	 * Check if value is an object.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if object
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_object(ctx, index);
+	}
+
+	/**
+	 * Create an empty object on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const Object &)
+	{
+		duk_push_object(ctx);
+	}
+};
+
+/**
+ * @class TypeInfo<Array>
+ * @brief Push empty array to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeInfo<Array> {
+public:
+	/**
+	 * Check if value is a array.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if array
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_array(ctx, index);
+	}
+
+	/**
+	 * Create an empty array on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const Array &)
+	{
+		duk_push_array(ctx);
+	}
+};
+
+/**
+ * @class TypeInfo<Undefined>
+ * @brief Push undefined value to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeInfo<Undefined> {
+public:
+	/**
+	 * Check if value is undefined.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if undefined
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_undefined(ctx, index);
+	}
+
+	/**
+	 * Push undefined value on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const Undefined &)
+	{
+		duk_push_undefined(ctx);
+	}
+};
+
+/**
+ * @class TypeInfo<Null>
+ * @brief Push null value to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeInfo<Null> {
+public:
+	/**
+	 * Check if value is null.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if null
+	 */
+	static inline bool is(Context &ctx, int index)
+	{
+		return duk_is_null(ctx, index);
+	}
+
+	/**
+	 * Push null value on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const Null &)
+	{
+		duk_push_null(ctx);
+	}
+};
+
+/**
+ * @brief Push this binding into the stack.
+ *
+ * Provides: push.
+ */
+template <>
+class TypeInfo<This> {
+public:
+	/**
+	 * Push this function into the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const This &)
+	{
+		duk_push_this(ctx);
+	}
+};
+
+/**
+ * @class TypeInfo<Global>
+ * @brief Push the global object to the stack.
+ *
+ * Provides: push.
+ */
+template <>
+class TypeInfo<Global> {
+public:
+	/**
+	 * Push the global object into the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(Context &ctx, const Global &)
+	{
+		duk_push_global_object(ctx);
+	}
+};
+
+/**
+ * @brief Push a map of key-value pair as objects.
+ *
+ * Provides: push.
+ *
+ * This class is convenient for settings constants such as enums, string and such.
+ */
+template <typename T>
+class TypeInfo<std::unordered_map<std::string, T>> {
+public:
+	/**
+	 * Put all values from the map as properties to the object at the top of the stack.
+	 *
+	 * @param ctx the context
+	 * @param map the values
+	 * @note You need an object at the top of the stack before calling this function
+	 */
+	static void push(Context &ctx, const std::unordered_map<std::string, T> &map)
+	{
+		for (const auto &pair : map) {
+			TypeInfo<T>::push(ctx, pair.second);
+			duk_put_prop_string(ctx, -2, pair.first.c_str());
+		}
+	}
+};
+
+/**
+ * @brief Push or get vectors as JavaScript arrays.
+ *
+ * Provides: get, push.
+ */
+template <typename T>
+class TypeInfo<std::vector<T>> {
+public:
+	/**
+	 * Get an array from the stack.
+	 *
+	 * @param ctx the context
+	 * @param index the array index
+	 * @return the array or empty array if the value is not an array
+	 */
+	static std::vector<T> get(Context &ctx, int index)
+	{
+		std::vector<T> result;
+
+		if (!duk_is_array(ctx, -1)) {
+			return result;
+		}
+
+		int total = duk_get_length(ctx, index);
+		for (int i = 0; i < total; ++i) {
+			result.push_back(ctx.getProperty<T>(index, i));
+		}
+
+		return result;
+	}
+
+	/**
+	 * Create an array with the specified values.
+	 *
+	 * @param ctx the context
+	 * @param array the values
+	 */
+	static void push(Context &ctx, const std::vector<T> &array)
+	{
+		duk_push_array(ctx);
+
+		int i = 0;
+		for (const auto &v : array) {
+			TypeInfo<T>::push(ctx, v);
+			duk_put_prop_index(ctx, -2, i++);
+		}
+	}
+};
+
+/**
+ * @brief Implementation of managed shared_ptr
+ * @see Shared
+ */
+template <typename T>
+class TypeInfo<Shared<T>> {
+private:
+	static void apply(Context &ctx, std::shared_ptr<T> value)
+	{
+		duk_push_boolean(ctx, false);
+		duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
+		duk_push_pointer(ctx, new std::shared_ptr<T>(value));
+		duk_put_prop_string(ctx, -2, "\xff""\xff""js-shared-ptr");
+		duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
+			duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+
+			if (!duk_to_boolean(ctx, -1)) {
+				duk_push_boolean(ctx, true);
+				duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+				duk_get_prop_string(ctx, 0, "\xff""\xff""js-shared-ptr");
+				delete static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
+				duk_pop(ctx);
+			}
+
+			duk_pop(ctx);
+
+			return 0;
+		}, 1);
+		duk_set_finalizer(ctx, -2);
+	}
+
+public:
+	/**
+	 * Construct the shared_ptr as this.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void construct(Context &ctx, Shared<T> value)
+	{
+		duk_push_this(ctx);
+		apply(ctx, std::move(value.object));
+		duk_pop(ctx);
+	}
+
+	/**
+	 * Push a managed shared_ptr as object.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void push(Context &ctx, Shared<T> value)
+	{
+		duk_push_object(ctx);
+		apply(ctx, value.object);
+		value.object->prototype(ctx);
+		duk_set_prototype(ctx, -2);
+	}
+
+	/**
+	 * Get a managed shared_ptr from the stack.
+	 *
+	 * @param ctx the context
+	 * @param index the object index
+	 * @return the shared_ptr
+	 */
+	static std::shared_ptr<T> get(Context &ctx, int 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 TypeInfo<Pointer<T>> {
+private:
+	static void apply(Context &ctx, T *value)
+	{
+		duk_push_boolean(ctx, false);
+		duk_put_prop_string(ctx, -2, "\xff""\xff""js-deleted");
+		duk_push_pointer(ctx, value);
+		duk_put_prop_string(ctx, -2, "\xff""\xff""js-ptr");
+		duk_push_c_function(ctx, [] (duk_context *ctx) -> duk_ret_t {
+			duk_get_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+
+			if (!duk_to_boolean(ctx, -1)) {
+				duk_push_boolean(ctx, true);
+				duk_put_prop_string(ctx, 0, "\xff""\xff""js-deleted");
+				duk_get_prop_string(ctx, 0, "\xff""\xff""js-ptr");
+				delete static_cast<T *>(duk_to_pointer(ctx, -1));
+				duk_pop(ctx);
+			}
+
+			duk_pop(ctx);
+
+			return 0;
+		}, 1);
+		duk_set_finalizer(ctx, -2);
+	}
+
+public:
+	/**
+	 * Construct the pointer as this.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void construct(Context &ctx, Pointer<T> value)
+	{
+		duk_push_this(ctx);
+		apply(ctx, value.object);
+		duk_pop(ctx);
+	}
+
+	/**
+	 * Push a managed pointer as object.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void push(Context &ctx, Pointer<T> value)
+	{
+		duk_push_object(ctx);
+		apply(ctx, value.object);
+		value.object->prototype(ctx);
+		duk_set_prototype(ctx, -2);
+	}
+
+	/**
+	 * 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(Context &ctx, int index)
+	{
+		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;
+	}
+};
+
+} // !js
+
+#endif // !_JS_H_
--- a/C++/tests/Js/main.cpp	Fri Oct 16 08:50:20 2015 +0200
+++ b/C++/tests/Js/main.cpp	Mon Oct 19 13:57:52 2015 +0200
@@ -647,6 +647,19 @@
 
 class Dog {
 public:
+	bool &m_deleted;
+	bool m_updated{false};
+
+	Dog(bool &deleted)
+		: m_deleted{deleted}
+	{
+	}
+
+	~Dog()
+	{
+		m_deleted = true;
+	}
+
 	void prototype(Context &ctx)
 	{
 		/* Create a temporary for the test */
@@ -659,27 +672,34 @@
 			return 0;
 		}});
 	}
-
-	bool m_updated{false};
 };
 
 TEST(Shared, simple)
 {
-	Context ctx;
-	std::shared_ptr<Dog> p{new Dog};
+	bool deleted{false};
+	{
+		std::shared_ptr<Dog> p{new Dog(deleted)};
+
+		{
+			Context ctx;
 
-	ctx.push(Shared<Dog>{p});
-	std::shared_ptr<Dog> p2 = ctx.get<Shared<Dog>>(-1);
+			ctx.push(Shared<Dog>{p});
+			std::shared_ptr<Dog> p2 = ctx.get<Shared<Dog>>(-1);
+
+			p2->m_updated = true;
 
-	p2->m_updated = true;
+			ASSERT_TRUE(p->m_updated);
+		}
+	}
 
-	ASSERT_TRUE(p->m_updated);
+	ASSERT_TRUE(deleted);
 }
 
 TEST(Shared, self)
 {
+	bool deleted{false};
 	Context ctx;
-	std::shared_ptr<Dog> p{new Dog};
+	std::shared_ptr<Dog> p{new Dog(deleted)};
 
 	try {
 		ctx.putGlobal("player", Shared<Dog>{p});
@@ -697,6 +717,19 @@
 
 class Cat {
 public:
+	bool &m_deleted;
+	bool m_updated{false};
+
+	Cat(bool &deleted)
+		: m_deleted{deleted}
+	{
+	}
+
+	~Cat()
+	{
+		m_deleted = true;
+	}
+
 	void prototype(Context &ctx)
 	{
 		/* Create a temporary for the test */
@@ -709,29 +742,33 @@
 			return 0;
 		}});
 	}
-
-	bool m_updated{false};
 };
 
 TEST(Pointer, simple)
 {
-	Context context;
-	Cat *p{new Cat};
+	bool deleted{false};
+	Cat *p{new Cat(deleted)};
 
-	ASSERT_EQ(0, context.top());
-	context.push(Pointer<Cat>{p});
-	Cat *p2 = context.get<Pointer<Cat>>(-1);
-	ASSERT_EQ(1, context.top());
+	{
+		Context context;
+	
+		ASSERT_EQ(0, context.top());
+		context.push(Pointer<Cat>{p});
+		Cat *p2 = context.get<Pointer<Cat>>(-1);
+		ASSERT_EQ(1, context.top());
+	
+		p2->m_updated = true;
+		ASSERT_TRUE(p->m_updated);
+	}
 
-	p2->m_updated = true;
-
-	ASSERT_TRUE(p->m_updated);
+	ASSERT_TRUE(deleted);
 }
 
 TEST(Pointer, self)
 {
+	bool deleted;
 	Context ctx;
-	Cat *p{new Cat};
+	Cat *p{new Cat(deleted)};
 
 	try {
 		ctx.putGlobal("player", Pointer<Cat>{p});