changeset 417:865224c2191a

Js: update documentation
author David Demelier <markand@malikania.fr>
date Thu, 08 Oct 2015 10:02:37 +0200
parents a93dfbb65648
children 30e4a93f86c7
files C++/modules/Js/Js.h C++/tests/Js/main.cpp
diffstat 2 files changed, 722 insertions(+), 323 deletions(-) [+]
line wrap: on
line diff
--- a/C++/modules/Js/Js.h	Thu Oct 08 08:39:47 2015 +0200
+++ b/C++/modules/Js/Js.h	Thu Oct 08 10:02:37 2015 +0200
@@ -39,6 +39,9 @@
 
 #include <duktape.h>
 
+/**
+ * Duktape C++ namespace wrapper.
+ */
 namespace js {
 
 class Context;
@@ -120,7 +123,7 @@
 using FunctionMap = std::unordered_map<std::string, Function>;
 
 /**
- * Map of string to type constant.
+ * Map of string to type, ideal for setting constants like enums.
  */
 template <typename Type>
 using Map = std::unordered_map<std::string, Type>;
@@ -194,13 +197,26 @@
  */
 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());
@@ -215,13 +231,26 @@
  */
 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());
@@ -286,212 +315,13 @@
 		return m_handle.get();
 	}
 
-	/* ----------------------------------------------------------
-	 * Push / Get / Require / Is / Optional
-	 * ---------------------------------------------------------- */
-
-	/**
-	 * 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)`.
+	/*
+	 * Basic functions
+	 * ----------------------------------------------------------
 	 *
-	 * @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));
-	}
-
-	/* --------------------------------------------------------
-	 * Get properties (for objects and arrays)
-	 * -------------------------------------------------------- */
-
-	/**
-	 * 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
+	 * 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.
 	 */
-	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);
-	}
-
-	/* --------------------------------------------------------
-	 * Put properties functions (for object)
-	 * -------------------------------------------------------- */
-
-	/**
-	 * 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);
-	}
-
-	/* --------------------------------------------------------
-	 * Basic functions
-	 * -------------------------------------------------------- */
-
-	/**
-	 * 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);
 
 	/**
 	 * Get the type of the value at the specified index.
@@ -621,19 +451,6 @@
 	}
 
 	/**
-	 * Call in protected mode the object at the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param nargs the number of arguments
-	 * @throw ErrorInfo on errors
-	 */
-	void pcall(unsigned nargs = 0);
-
-	/* ------------------------------------------------------------------
-	 * Eval functions
-	 * ------------------------------------------------------------------ */
-
-	/**
 	 * Evaluate a non-protected chunk that is at the top of the stack.
 	 *
 	 * @param ctx
@@ -643,6 +460,23 @@
 		duk_eval(m_handle.get());
 	}
 
+	/*
+	 * 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 ctx the context
+	 * @param nargs the number of arguments
+	 * @throw ErrorInfo on errors
+	 */
+	void pcall(unsigned nargs = 0);
+
 	/**
 	 * Evaluate a non-protected source.
 	 *
@@ -659,7 +493,6 @@
 	/**
 	 * Evaluate a protected chunk that is at the top of the stack.
 	 *
-	 * @param ctx the context
 	 * @throw ErrorInfo the error
 	 */
 	void peval();
@@ -683,14 +516,270 @@
 		}
 	}
 
-	/* ------------------------------------------------------------------
-	 * Extended functions
-	 * ------------------------------------------------------------------ */
+	/*
+	 * 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 ctx the context
 	 * @param index the object or array index
 	 * @param flags the optional flags to pass to duk_enum
 	 * @param getvalue set to true if you want to extract the value
@@ -727,7 +816,6 @@
 	/**
 	 * Throw an ECMAScript exception.
 	 *
-	 * @param ctx the context
 	 * @param ex the exception
 	 */
 	template <typename Exception>
@@ -755,60 +843,6 @@
 	{
 		TypeInfo<std::decay_t<T>>::construct(*this, std::forward<T>(value));
 	}
-
-	/* --------------------------------------------------------
-	 * Global functions
-	 * -------------------------------------------------------- */
-
-	/**
-	 * Get a global value.
-	 *
-	 * @param ctx the context
-	 * @param name the name of the global variable
-	 * @return the value
-	 */
-	template <typename Type>
-	inline auto getGlobal(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 ctx the context
-	 * @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());
-	}
 };
 
 /* ------------------------------------------------------------------
@@ -868,6 +902,11 @@
  */
 class Error : public ExceptionAbstract {
 public:
+	/**
+	 * Constructor with a message.
+	 *
+	 * @param message the message
+	 */
 	inline Error(std::string message) noexcept
 		: ExceptionAbstract{"Error", std::move(message)}
 	{
@@ -880,6 +919,9 @@
  */
 class EvalError : public ExceptionAbstract {
 public:
+	/**
+	 * @copydoc Error
+	 */
 	inline EvalError(std::string message) noexcept
 		: ExceptionAbstract{"EvalError", std::move(message)}
 	{
@@ -892,6 +934,9 @@
  */
 class RangeError : public ExceptionAbstract {
 public:
+	/**
+	 * @copydoc Error
+	 */
 	inline RangeError(std::string message) noexcept
 		: ExceptionAbstract{"RangeError", std::move(message)}
 	{
@@ -904,6 +949,9 @@
  */
 class ReferenceError : public ExceptionAbstract {
 public:
+	/**
+	 * @copydoc Error
+	 */
 	inline ReferenceError(std::string message) noexcept
 		: ExceptionAbstract{"ReferenceError", std::move(message)}
 	{
@@ -916,6 +964,9 @@
  */
 class SyntaxError : public ExceptionAbstract {
 public:
+	/**
+	 * @copydoc Error
+	 */
 	inline SyntaxError(std::string message) noexcept
 		: ExceptionAbstract{"SyntaxError", std::move(message)}
 	{
@@ -928,6 +979,9 @@
  */
 class TypeError : public ExceptionAbstract {
 public:
+	/**
+	 * @copydoc Error
+	 */
 	inline TypeError(std::string message) noexcept
 		: ExceptionAbstract{"TypeError", std::move(message)}
 	{
@@ -940,6 +994,9 @@
  */
 class URIError : public ExceptionAbstract {
 public:
+	/**
+	 * @copydoc Error
+	 */
 	inline URIError(std::string message) noexcept
 		: ExceptionAbstract{"URIError", std::move(message)}
 	{
@@ -959,16 +1016,38 @@
 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)) {
@@ -978,11 +1057,24 @@
 		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);
@@ -998,16 +1090,38 @@
 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)) {
@@ -1017,11 +1131,24 @@
 		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);
@@ -1037,16 +1164,38 @@
 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)) {
@@ -1056,11 +1205,24 @@
 		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);
@@ -1078,6 +1240,13 @@
 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;
@@ -1086,11 +1255,26 @@
 		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)) {
@@ -1100,11 +1284,24 @@
 		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;
@@ -1123,16 +1320,38 @@
 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)) {
@@ -1142,11 +1361,24 @@
 		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);
@@ -1154,6 +1386,79 @@
 };
 
 /**
+ * @brief Implementation for non-managed pointers.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <typename T>
+class TypeInfo<Pointer<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, Pointer<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 Pointer<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.
  *
@@ -1164,6 +1469,13 @@
 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);
 };
 
@@ -1176,6 +1488,12 @@
 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) {
@@ -1193,11 +1511,23 @@
 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);
@@ -1213,11 +1543,23 @@
 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);
@@ -1233,11 +1575,23 @@
 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);
@@ -1253,11 +1607,23 @@
 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);
@@ -1265,44 +1631,6 @@
 };
 
 /**
- * @brief Implementation for non-managed pointers.
- *
- * Provides: get, is, optional, push, require.
- */
-template <typename T>
-class TypeInfo<Pointer<T>> {
-public:
-	static inline T *get(Context &ctx, int index)
-	{
-		return static_cast<T *>(duk_to_pointer(ctx, index));
-	}
-
-	static inline bool is(Context &ctx, int index)
-	{
-		return duk_is_pointer(ctx, index);
-	}
-
-	static inline T *optional(Context &ctx, int index, Pointer<T> defaultValue)
-	{
-		if (!duk_is_pointer(ctx, index)) {
-			return defaultValue.object;
-		}
-
-		return static_cast<T *>(duk_to_pointer(ctx, index));
-	}
-
-	static inline void push(Context &ctx, const Pointer<T> &p)
-	{
-		duk_push_pointer(ctx, p.object);
-	}
-
-	static inline T *require(Context &ctx, int index)
-	{
-		return static_cast<T *>(duk_require_pointer(ctx, index));
-	}
-};
-
-/**
  * @class TypeInfo<Global>
  * @brief Push the global object to the stack.
  *
@@ -1311,6 +1639,11 @@
 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);
@@ -1325,9 +1658,16 @@
  * This class is convenient for settings constants such as enums, string and such.
  */
 template <typename T>
-class TypeInfo<Map<T>> {
+class TypeInfo<std::unordered_map<std::string, T>> {
 public:
-	static void push(Context &ctx, const Map<T> &map)
+	/**
+	 * 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);
@@ -1344,6 +1684,13 @@
 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;
@@ -1360,6 +1707,12 @@
 		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);
@@ -1380,7 +1733,7 @@
  * @class TypeInfoShared
  * @brief Push objects as shared_ptr.
  *
- * TODO: add better documentation when finalized.
+ * Overload TypeInfo<T *> and inherits from this class to implement constrct, push and get function automatically.
  */
 template <typename T>
 class TypeInfoShared {
@@ -1388,8 +1741,29 @@
 	static void apply(Context &ctx, std::shared_ptr<T> value);
 
 public:
+	/**
+	 * Construct the shared_ptr as this.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
 	static void construct(Context &ctx, std::shared_ptr<T> value);
+
+	/**
+	 * Push a managed shared_ptr as object.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
 	static void push(Context &ctx, std::shared_ptr<T> value);
+
+	/**
+	 * 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);
 };
 
@@ -1451,9 +1825,12 @@
 
 /**
  * @class TypeInfoPointer
- * @brief Push pointers as objects.
+ * @brief Push managed pointers as objects.
  *
- * TODO: add better documentation when finalized.
+ * Overload TypeInfo<T *> and inherits from this class to implement constrct, push and get function automatically,
+ * the pointer is constructed and managed into the Duktape context. It will be deleted when the Duktape garbage
+ * collectors collects the value. It is unsafe to keep a pointer to the object from the C++ side, if you need
+ * to share values, look at TypeInfoShared.
  */
 template <typename T>
 class TypeInfoPointer {
@@ -1461,8 +1838,30 @@
 	static void apply(Context &ctx, T *value);
 
 public:
+	/**
+	 * Construct the pointer as this.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
 	static void construct(Context &ctx, T *value);
+
+	/**
+	 * Push a managed pointer as object.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
 	static void push(Context &ctx, T *value);
+
+	/**
+	 * 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);
 };
 
--- a/C++/tests/Js/main.cpp	Thu Oct 08 08:39:47 2015 +0200
+++ b/C++/tests/Js/main.cpp	Thu Oct 08 10:02:37 2015 +0200
@@ -112,7 +112,7 @@
 	};
 
 	ASSERT_EQ(0, context.top());
-	context.push(js::Object{});
+	context.push(Object{});
 	context.push(map);
 
 	ASSERT_EQ(DUK_TYPE_OBJECT, context.type(-1));
@@ -440,7 +440,7 @@
 	Context context;
 
 	ASSERT_EQ(0, context.top());
-	ASSERT_EQ(nullptr, context.optional<js::Pointer<int>>(0, js::Pointer<int>{nullptr}));
+	ASSERT_EQ(nullptr, context.optional<Pointer<int>>(0, Pointer<int>{nullptr}));
 	ASSERT_EQ(0, context.top());
 }