changeset 351:15da984ce7ea

Irccd: revert ownership as it's a cleaner solution
author David Demelier <markand@malikania.fr>
date Mon, 14 Nov 2016 13:32:38 +0100
parents 287e9ede5eef
children aab46e17cb27
files libirccd-js/irccd/mod-directory.cpp libirccd-js/irccd/mod-directory.hpp libirccd-js/irccd/mod-elapsed-timer.cpp libirccd-js/irccd/mod-elapsed-timer.hpp libirccd-js/irccd/mod-file.cpp libirccd-js/irccd/mod-file.hpp libirccd-js/irccd/mod-irccd.cpp libirccd-js/irccd/mod-irccd.hpp libirccd-js/irccd/mod-logger.cpp libirccd-js/irccd/mod-logger.hpp libirccd-js/irccd/mod-plugin.cpp libirccd-js/irccd/mod-plugin.hpp libirccd-js/irccd/mod-server.cpp libirccd-js/irccd/mod-server.hpp libirccd-js/irccd/mod-system.cpp libirccd-js/irccd/mod-system.hpp libirccd-js/irccd/mod-timer.cpp libirccd-js/irccd/mod-timer.hpp libirccd-js/irccd/mod-unicode.cpp libirccd-js/irccd/mod-unicode.hpp libirccd-js/irccd/mod-util.cpp libirccd-js/irccd/mod-util.hpp libirccd-js/irccd/module.hpp libirccd-js/irccd/plugin-js.cpp tests/js-elapsedtimer/main.cpp tests/js-file/main.cpp tests/js-irccd/main.cpp tests/js-logger/main.cpp tests/js-system/main.cpp tests/js-timer/main.cpp tests/js-unicode/main.cpp tests/js-util/main.cpp
diffstat 32 files changed, 231 insertions(+), 231 deletions(-) [+]
line wrap: on
line diff
--- a/libirccd-js/irccd/mod-directory.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-directory.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -371,21 +371,21 @@
 {
 }
 
-void DirectoryModule::load(Irccd &, JsPlugin &plugin)
+void DirectoryModule::load(Irccd &, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
-    duk_get_global_string(plugin.context(), "Irccd");
-    duk_push_c_function(plugin.context(), constructor, 2);
-    duk_put_number_list(plugin.context(), -1, constants);
-    duk_put_function_list(plugin.context(), -1, functions);
-    dukx_push_std_string(plugin.context(), std::string{fs::separator()});
-    duk_put_prop_string(plugin.context(), -2, "separator");
-    duk_push_object(plugin.context());
-    duk_put_function_list(plugin.context(), -1, methods);
-    duk_put_prop_string(plugin.context(), -2, "prototype");
-    duk_put_prop_string(plugin.context(), -2, "Directory");
-    duk_pop(plugin.context());
+    duk_get_global_string(plugin->context(), "Irccd");
+    duk_push_c_function(plugin->context(), constructor, 2);
+    duk_put_number_list(plugin->context(), -1, constants);
+    duk_put_function_list(plugin->context(), -1, functions);
+    dukx_push_std_string(plugin->context(), std::string{fs::separator()});
+    duk_put_prop_string(plugin->context(), -2, "separator");
+    duk_push_object(plugin->context());
+    duk_put_function_list(plugin->context(), -1, methods);
+    duk_put_prop_string(plugin->context(), -2, "prototype");
+    duk_put_prop_string(plugin->context(), -2, "Directory");
+    duk_pop(plugin->context());
 }
 
 } // !irccd
--- a/libirccd-js/irccd/mod-directory.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-directory.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -42,7 +42,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 } // !irccd
--- a/libirccd-js/irccd/mod-elapsed-timer.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-elapsed-timer.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -143,19 +143,19 @@
 {
 }
 
-void ElapsedTimerModule::load(Irccd &, JsPlugin &plugin)
+void ElapsedTimerModule::load(Irccd &, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
-    duk_get_global_string(plugin.context(), "Irccd");
-    duk_push_c_function(plugin.context(), constructor, 0);
-    duk_push_object(plugin.context());
-    duk_put_function_list(plugin.context(), -1, methods);
-    duk_push_c_function(plugin.context(), destructor, 1);
-    duk_set_finalizer(plugin.context(), -2);
-    duk_put_prop_string(plugin.context(), -2, "prototype");
-    duk_put_prop_string(plugin.context(), -2, "ElapsedTimer");
-    duk_pop(plugin.context());
+    duk_get_global_string(plugin->context(), "Irccd");
+    duk_push_c_function(plugin->context(), constructor, 0);
+    duk_push_object(plugin->context());
+    duk_put_function_list(plugin->context(), -1, methods);
+    duk_push_c_function(plugin->context(), destructor, 1);
+    duk_set_finalizer(plugin->context(), -2);
+    duk_put_prop_string(plugin->context(), -2, "prototype");
+    duk_put_prop_string(plugin->context(), -2, "ElapsedTimer");
+    duk_pop(plugin->context());
 }
 
 } // !irccd
--- a/libirccd-js/irccd/mod-elapsed-timer.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-elapsed-timer.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -42,7 +42,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 } // !irccd
--- a/libirccd-js/irccd/mod-file.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-file.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -632,23 +632,23 @@
 {
 }
 
-void FileModule::load(Irccd &, JsPlugin &plugin)
+void FileModule::load(Irccd &, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
-    duk_get_global_string(plugin.context(), "Irccd");
-    duk_push_c_function(plugin.context(), constructor, 2);
-    duk_put_number_list(plugin.context(), -1, constants);
-    duk_put_function_list(plugin.context(), -1, functions);
-    duk_push_object(plugin.context());
-    duk_put_function_list(plugin.context(), -1, methods);
-    duk_push_c_function(plugin.context(), destructor, 1);
-    duk_set_finalizer(plugin.context(), -2);
-    duk_dup(plugin.context(), -1);
-    duk_put_global_string(plugin.context(), Prototype);
-    duk_put_prop_string(plugin.context(), -2, "prototype");
-    duk_put_prop_string(plugin.context(), -2, "File");
-    duk_pop(plugin.context());
+    duk_get_global_string(plugin->context(), "Irccd");
+    duk_push_c_function(plugin->context(), constructor, 2);
+    duk_put_number_list(plugin->context(), -1, constants);
+    duk_put_function_list(plugin->context(), -1, functions);
+    duk_push_object(plugin->context());
+    duk_put_function_list(plugin->context(), -1, methods);
+    duk_push_c_function(plugin->context(), destructor, 1);
+    duk_set_finalizer(plugin->context(), -2);
+    duk_dup(plugin->context(), -1);
+    duk_put_global_string(plugin->context(), Prototype);
+    duk_put_prop_string(plugin->context(), -2, "prototype");
+    duk_put_prop_string(plugin->context(), -2, "File");
+    duk_pop(plugin->context());
 }
 
 void dukx_new_file(duk_context *ctx, File *fp)
--- a/libirccd-js/irccd/mod-file.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-file.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -148,7 +148,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 /**
--- a/libirccd-js/irccd/mod-irccd.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-irccd.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -155,46 +155,46 @@
 {
 }
 
-void IrccdModule::load(Irccd &irccd, JsPlugin &plugin)
+void IrccdModule::load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
     // Irccd.
-    duk_push_object(plugin.context());
+    duk_push_object(plugin->context());
 
     // Version.
-    duk_push_object(plugin.context());
-    duk_push_int(plugin.context(), IRCCD_VERSION_MAJOR);
-    duk_put_prop_string(plugin.context(), -2, "major");
-    duk_push_int(plugin.context(), IRCCD_VERSION_MINOR);
-    duk_put_prop_string(plugin.context(), -2, "minor");
-    duk_push_int(plugin.context(), IRCCD_VERSION_PATCH);
-    duk_put_prop_string(plugin.context(), -2, "patch");
-    duk_put_prop_string(plugin.context(), -2, "version");
+    duk_push_object(plugin->context());
+    duk_push_int(plugin->context(), IRCCD_VERSION_MAJOR);
+    duk_put_prop_string(plugin->context(), -2, "major");
+    duk_push_int(plugin->context(), IRCCD_VERSION_MINOR);
+    duk_put_prop_string(plugin->context(), -2, "minor");
+    duk_push_int(plugin->context(), IRCCD_VERSION_PATCH);
+    duk_put_prop_string(plugin->context(), -2, "patch");
+    duk_put_prop_string(plugin->context(), -2, "version");
 
     // Create the SystemError that inherits from Error.
-    duk_push_c_function(plugin.context(), constructor, 2);
+    duk_push_c_function(plugin->context(), constructor, 2);
 
     // Put errno codes into the Irccd.SystemError object.
     for (const auto &pair : errors) {
-        duk_push_int(plugin.context(), pair.second);
-        duk_put_prop_string(plugin.context(), -2, pair.first.c_str());
+        duk_push_int(plugin->context(), pair.second);
+        duk_put_prop_string(plugin->context(), -2, pair.first.c_str());
     }
 
-    duk_push_object(plugin.context());
-    duk_get_global_string(plugin.context(), "Error");
-    duk_get_prop_string(plugin.context(), -1, "prototype");
-    duk_remove(plugin.context(), -2);
-    duk_set_prototype(plugin.context(), -2);
-    duk_put_prop_string(plugin.context(), -2, "prototype");
-    duk_put_prop_string(plugin.context(), -2, "SystemError");
+    duk_push_object(plugin->context());
+    duk_get_global_string(plugin->context(), "Error");
+    duk_get_prop_string(plugin->context(), -1, "prototype");
+    duk_remove(plugin->context(), -2);
+    duk_set_prototype(plugin->context(), -2);
+    duk_put_prop_string(plugin->context(), -2, "prototype");
+    duk_put_prop_string(plugin->context(), -2, "SystemError");
 
     // Set Irccd as global.
-    duk_put_global_string(plugin.context(), "Irccd");
+    duk_put_global_string(plugin->context(), "Irccd");
 
     // Store global instance.
-    duk_push_pointer(plugin.context(), &irccd);
-    duk_put_global_string(plugin.context(), "\xff""\xff""irccd-ref");
+    duk_push_pointer(plugin->context(), &irccd);
+    duk_put_global_string(plugin->context(), "\xff""\xff""irccd-ref");
 }
 
 Irccd &dukx_get_irccd(duk_context *ctx)
--- a/libirccd-js/irccd/mod-irccd.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-irccd.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -77,7 +77,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 /**
--- a/libirccd-js/irccd/mod-logger.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-logger.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -27,7 +27,7 @@
 
 duk_ret_t print(duk_context *ctx, std::ostream &out)
 {
-    out << "plugin " << dukx_get_plugin(ctx).name() << ": " << duk_require_string(ctx, 0) << std::endl;
+    out << "plugin " << dukx_get_plugin(ctx)->name() << ": " << duk_require_string(ctx, 0) << std::endl;
 
     return 0;
 }
@@ -88,15 +88,15 @@
 {
 }
 
-void LoggerModule::load(Irccd &, JsPlugin &plugin)
+void LoggerModule::load(Irccd &, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
-    duk_get_global_string(plugin.context(), "Irccd");
-    duk_push_object(plugin.context());
-    duk_put_function_list(plugin.context(), -1, functions);
-    duk_put_prop_string(plugin.context(), -2, "Logger");
-    duk_pop(plugin.context());
+    duk_get_global_string(plugin->context(), "Irccd");
+    duk_push_object(plugin->context());
+    duk_put_function_list(plugin->context(), -1, functions);
+    duk_put_prop_string(plugin->context(), -2, "Logger");
+    duk_pop(plugin->context());
 }
 
 } // !irccd
--- a/libirccd-js/irccd/mod-logger.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-logger.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -42,7 +42,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 } // !irccd
--- a/libirccd-js/irccd/mod-plugin.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-plugin.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * js-plugin.cpp -- Irccd.Plugin API
+ * js-plugin->cpp -- Irccd.Plugin API
  *
  * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
  *
@@ -58,7 +58,7 @@
  * set
  * ------------------------------------------------------------------
  *
- * This setter is used to replace the Irccd.Plugin.(config|format) property when
+ * This setter is used to replace the Irccd.plugin->(config|format) property when
  * the plugin assign a new one.
  *
  * Because the plugin configuration always has higher priority, when a new
@@ -69,20 +69,20 @@
  *
  * Plugin 'xyz' does:
  *
- * Irccd.Plugin.config = {
+ * Irccd.plugin->config = {
  *      mode: "simple",
  *      level: "123"
  * };
  *
  * The user configuration is:
  *
- * [plugin.xyz]
+ * [plugin->xyz]
  * mode = "hard"
  * path = "/var"
  *
  * The final user table looks like this:
  *
- * Irccd.Plugin.config = {
+ * Irccd.plugin->config = {
  *      mode: "hard",
  *      level: "123",
  *      path: "/var"
@@ -112,7 +112,7 @@
  * get
  * ------------------------------------------------------------------
  *
- * Get the Irccd.Plugin.(config|format) property.
+ * Get the Irccd.plugin->(config|format) property.
  */
 duk_ret_t get(duk_context *ctx, const char *name)
 {
@@ -125,7 +125,7 @@
  * setConfig
  * ------------------------------------------------------------------
  *
- * Wrap setter for Irccd.Plugin.config property.
+ * Wrap setter for Irccd.plugin->config property.
  */
 duk_ret_t setConfig(duk_context *ctx)
 {
@@ -136,7 +136,7 @@
  * getConfig
  * ------------------------------------------------------------------
  *
- * Wrap getter for Irccd.Plugin.config property.
+ * Wrap getter for Irccd.plugin->config property.
  */
 duk_ret_t getConfig(duk_context *ctx)
 {
@@ -147,7 +147,7 @@
  * setFormat
  * ------------------------------------------------------------------
  *
- * Wrap setter for Irccd.Plugin.format property.
+ * Wrap setter for Irccd.plugin->format property.
  */
 duk_ret_t setFormat(duk_context *ctx)
 {
@@ -158,7 +158,7 @@
  * getFormat
  * ------------------------------------------------------------------
  *
- * Wrap getter for Irccd.Plugin.format property.
+ * Wrap getter for Irccd.plugin->format property.
  */
 duk_ret_t getFormat(duk_context *ctx)
 {
@@ -166,10 +166,10 @@
 }
 
 /*
- * Function: Irccd.Plugin.info([name])
+ * Function: Irccd.plugin->info([name])
  * ------------------------------------------------------------------
  *
- * Get information about a plugin.
+ * Get information about a plugin->
  *
  * The returned object as the following properties:
  *
@@ -187,12 +187,12 @@
  */
 duk_idx_t info(duk_context *ctx)
 {
-    Plugin *plugin = nullptr;
+    std::shared_ptr<Plugin> plugin;
 
     if (duk_get_top(ctx) >= 1)
-        plugin = dukx_get_irccd(ctx).plugins().get(duk_require_string(ctx, 0)).get();
+        plugin = dukx_get_irccd(ctx).plugins().get(duk_require_string(ctx, 0));
     else
-        plugin = &dukx_get_plugin(ctx);
+        plugin = dukx_get_plugin(ctx);
 
     if (!plugin)
         return 0;
@@ -213,7 +213,7 @@
 }
 
 /*
- * Function: Irccd.Plugin.list()
+ * Function: Irccd.plugin->list()
  * ------------------------------------------------------------------
  *
  * Get the list of plugins, the array returned contains all plugin names.
@@ -231,7 +231,7 @@
 }
 
 /*
- * Function: Irccd.Plugin.load(name)
+ * Function: Irccd.plugin->load(name)
  * ------------------------------------------------------------------
  *
  * Load a plugin by name. This function will search through the standard
@@ -251,7 +251,7 @@
 }
 
 /*
- * Function: Irccd.Plugin.reload(name)
+ * Function: Irccd.plugin->reload(name)
  * ------------------------------------------------------------------
  *
  * Reload a plugin by name.
@@ -270,7 +270,7 @@
 }
 
 /*
- * Function: Irccd.Plugin.unload(name)
+ * Function: Irccd.plugin->unload(name)
  * ------------------------------------------------------------------
  *
  * Unload a plugin by name.
@@ -304,38 +304,38 @@
 {
 }
 
-void PluginModule::load(Irccd &, JsPlugin &plugin)
+void PluginModule::load(Irccd &, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
-    duk_push_pointer(plugin.context(), &plugin);
-    duk_put_global_string(plugin.context(), PluginGlobal);
-    duk_get_global_string(plugin.context(), "Irccd");
-    duk_push_object(plugin.context());
-    duk_put_function_list(plugin.context(), -1, functions);
+    duk_push_pointer(plugin->context(), &plugin);
+    duk_put_global_string(plugin->context(), PluginGlobal);
+    duk_get_global_string(plugin->context(), "Irccd");
+    duk_push_object(plugin->context());
+    duk_put_function_list(plugin->context(), -1, functions);
 
     // 'config' property.
-    duk_push_string(plugin.context(), "config");
-    duk_push_c_function(plugin.context(), getConfig, 0);
-    duk_push_c_function(plugin.context(), setConfig, 1);
-    duk_def_prop(plugin.context(), -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
+    duk_push_string(plugin->context(), "config");
+    duk_push_c_function(plugin->context(), getConfig, 0);
+    duk_push_c_function(plugin->context(), setConfig, 1);
+    duk_def_prop(plugin->context(), -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
 
     // 'format' property.
-    duk_push_string(plugin.context(), "format");
-    duk_push_c_function(plugin.context(), getFormat, 0);
-    duk_push_c_function(plugin.context(), setFormat, 1);
-    duk_def_prop(plugin.context(), -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
+    duk_push_string(plugin->context(), "format");
+    duk_push_c_function(plugin->context(), getFormat, 0);
+    duk_push_c_function(plugin->context(), setFormat, 1);
+    duk_def_prop(plugin->context(), -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
 
-    duk_put_prop_string(plugin.context(), -2, "Plugin");
-    duk_pop(plugin.context());
+    duk_put_prop_string(plugin->context(), -2, "Plugin");
+    duk_pop(plugin->context());
 }
 
-JsPlugin &dukx_get_plugin(duk_context *ctx)
+std::shared_ptr<JsPlugin> dukx_get_plugin(duk_context *ctx)
 {
     StackAssert sa(ctx);
 
     duk_get_global_string(ctx, PluginGlobal);
-    auto plugin = static_cast<JsPlugin *>(duk_to_pointer(ctx, -1));
+    auto plugin = static_cast<std::shared_ptr<JsPlugin> *>(duk_to_pointer(ctx, -1));
     duk_pop(ctx);
 
     return *plugin;
--- a/libirccd-js/irccd/mod-plugin.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-plugin.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -43,7 +43,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, irccd::JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 /**
@@ -52,7 +52,7 @@
  * \param ctx the context
  * \return the plugin
  */
-JsPlugin &dukx_get_plugin(duk_context *ctx);
+std::shared_ptr<irccd::JsPlugin> dukx_get_plugin(duk_context *ctx);
 
 } // !irccd
 
--- a/libirccd-js/irccd/mod-server.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-server.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -533,22 +533,22 @@
 {
 }
 
-void ServerModule::load(Irccd &, JsPlugin &plugin)
+void ServerModule::load(Irccd &, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
-    duk_get_global_string(plugin.context(), "Irccd");
-    duk_push_c_function(plugin.context(), constructor, 1);
-    duk_put_function_list(plugin.context(), -1, functions);
-    duk_push_object(plugin.context());
-    duk_put_function_list(plugin.context(), -1, methods);
-    duk_push_c_function(plugin.context(), destructor, 1);
-    duk_set_finalizer(plugin.context(), -2);
-    duk_dup_top(plugin.context());
-    duk_put_global_string(plugin.context(), Prototype);
-    duk_put_prop_string(plugin.context(), -2, "prototype");
-    duk_put_prop_string(plugin.context(), -2, "Server");
-    duk_pop(plugin.context());
+    duk_get_global_string(plugin->context(), "Irccd");
+    duk_push_c_function(plugin->context(), constructor, 1);
+    duk_put_function_list(plugin->context(), -1, functions);
+    duk_push_object(plugin->context());
+    duk_put_function_list(plugin->context(), -1, methods);
+    duk_push_c_function(plugin->context(), destructor, 1);
+    duk_set_finalizer(plugin->context(), -2);
+    duk_dup_top(plugin->context());
+    duk_put_global_string(plugin->context(), Prototype);
+    duk_put_prop_string(plugin->context(), -2, "prototype");
+    duk_put_prop_string(plugin->context(), -2, "Server");
+    duk_pop(plugin->context());
 }
 
 void dukx_push_server(duk_context *ctx, std::shared_ptr<Server> server)
--- a/libirccd-js/irccd/mod-server.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-server.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -44,7 +44,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 /**
--- a/libirccd-js/irccd/mod-system.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-system.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -229,15 +229,15 @@
 {
 }
 
-void SystemModule::load(Irccd &, JsPlugin &plugin)
+void SystemModule::load(Irccd &, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
-    duk_get_global_string(plugin.context(), "Irccd");
-    duk_push_object(plugin.context());
-    duk_put_function_list(plugin.context(), -1, functions);
-    duk_put_prop_string(plugin.context(), -2, "System");
-    duk_pop(plugin.context());
+    duk_get_global_string(plugin->context(), "Irccd");
+    duk_push_object(plugin->context());
+    duk_put_function_list(plugin->context(), -1, functions);
+    duk_put_prop_string(plugin->context(), -2, "System");
+    duk_pop(plugin->context());
 }
 
 } // !irccd
--- a/libirccd-js/irccd/mod-system.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-system.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -42,7 +42,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 } // !irccd
--- a/libirccd-js/irccd/mod-timer.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-timer.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -37,30 +37,28 @@
 
 void handleSignal(std::weak_ptr<JsPlugin> ptr, std::string key)
 {
-#if 0
     auto plugin = ptr.lock();
 
     if (!plugin)
         return;
 
-    auto &irccd = dukx_get_irccd(plugin.context());
+    auto &irccd = dukx_get_irccd(plugin->context());
 
     irccd.post([plugin, key] (Irccd &) {
-        StackAssert sa(plugin.context());
+        StackAssert sa(plugin->context());
 
-        duk_get_global_string(plugin.context(), CallbackTable);
-        duk_get_prop_string(plugin.context(), -1, key.c_str());
-        duk_remove(plugin.context(), -2);
+        duk_get_global_string(plugin->context(), CallbackTable);
+        duk_get_prop_string(plugin->context(), -1, key.c_str());
+        duk_remove(plugin->context(), -2);
 
-        if (duk_is_callable(plugin.context(), -1)) {
-            if (duk_pcall(plugin.context(), 0) != 0)
-                log::warning("plugin {}: {}"_format(plugin.name(), dukx_exception(plugin.context(), -1).stack));
+        if (duk_is_callable(plugin->context(), -1)) {
+            if (duk_pcall(plugin->context(), 0) != 0)
+                log::warning("plugin {}: {}"_format(plugin->name(), dukx_exception(plugin->context(), -1).stack));
             else
-                duk_pop(plugin.context());
+                duk_pop(plugin->context());
         } else
-            duk_pop(plugin.context());
+            duk_pop(plugin->context());
     });
-#endif
 }
 
 std::shared_ptr<Timer> self(duk_context *ctx)
@@ -129,7 +127,6 @@
  */
 duk_ret_t constructor(duk_context *ctx)
 {
-#if 0
     // Check parameters.
     auto type = duk_require_int(ctx, 0);
     auto delay = duk_require_int(ctx, 1);
@@ -176,7 +173,7 @@
     duk_dup(ctx, 2);
     duk_put_prop_string(ctx, -2, hash.c_str());
     duk_pop(ctx);
-#endif
+
     return 0;
 }
 
@@ -193,20 +190,20 @@
 {
 }
 
-void TimerModule::load(Irccd &, JsPlugin &plugin)
+void TimerModule::load(Irccd &, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
-    duk_get_global_string(plugin.context(), "Irccd");
-    duk_push_c_function(plugin.context(), constructor, 3);
-    duk_put_number_list(plugin.context(), -1, constants);
-    duk_push_object(plugin.context());
-    duk_put_function_list(plugin.context(), -1, methods);
-    duk_put_prop_string(plugin.context(), -2, "prototype");
-    duk_put_prop_string(plugin.context(), -2, "Timer");
-    duk_pop(plugin.context());
-    duk_push_object(plugin.context());
-    duk_put_global_string(plugin.context(), CallbackTable);
+    duk_get_global_string(plugin->context(), "Irccd");
+    duk_push_c_function(plugin->context(), constructor, 3);
+    duk_put_number_list(plugin->context(), -1, constants);
+    duk_push_object(plugin->context());
+    duk_put_function_list(plugin->context(), -1, methods);
+    duk_put_prop_string(plugin->context(), -2, "prototype");
+    duk_put_prop_string(plugin->context(), -2, "Timer");
+    duk_pop(plugin->context());
+    duk_push_object(plugin->context());
+    duk_put_global_string(plugin->context(), CallbackTable);
 }
 
 } // !irccd
--- a/libirccd-js/irccd/mod-timer.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-timer.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -42,7 +42,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 } // !irccd
--- a/libirccd-js/irccd/mod-unicode.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-unicode.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -138,15 +138,15 @@
 {
 }
 
-void UnicodeModule::load(Irccd &, JsPlugin &plugin)
+void UnicodeModule::load(Irccd &, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
-    duk_get_global_string(plugin.context(), "Irccd");
-    duk_push_object(plugin.context());
-    duk_put_function_list(plugin.context(), -1, functions);
-    duk_put_prop_string(plugin.context(), -2, "Unicode");
-    duk_pop(plugin.context());
+    duk_get_global_string(plugin->context(), "Irccd");
+    duk_push_object(plugin->context());
+    duk_put_function_list(plugin->context(), -1, functions);
+    duk_put_prop_string(plugin->context(), -2, "Unicode");
+    duk_pop(plugin->context());
 }
 
 } // !irccd
--- a/libirccd-js/irccd/mod-unicode.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-unicode.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -42,7 +42,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 } // !irccd
--- a/libirccd-js/irccd/mod-util.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-util.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -136,15 +136,15 @@
 {
 }
 
-void UtilModule::load(Irccd &, JsPlugin &plugin)
+void UtilModule::load(Irccd &, std::shared_ptr<JsPlugin> plugin)
 {
-    StackAssert sa(plugin.context());
+    StackAssert sa(plugin->context());
 
-    duk_get_global_string(plugin.context(), "Irccd");
-    duk_push_object(plugin.context());
-    duk_put_function_list(plugin.context(), -1, functions);
-    duk_put_prop_string(plugin.context(), -2, "Util");
-    duk_pop(plugin.context());
+    duk_get_global_string(plugin->context(), "Irccd");
+    duk_push_object(plugin->context());
+    duk_put_function_list(plugin->context(), -1, functions);
+    duk_put_prop_string(plugin->context(), -2, "Util");
+    duk_pop(plugin->context());
 }
 
 } // !irccd
--- a/libirccd-js/irccd/mod-util.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/mod-util.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -42,7 +42,7 @@
     /**
      * \copydoc Module::load
      */
-    IRCCD_EXPORT void load(Irccd &irccd, JsPlugin &plugin) override;
+    IRCCD_EXPORT void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin) override;
 };
 
 } // !irccd
--- a/libirccd-js/irccd/module.hpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/module.hpp	Mon Nov 14 13:32:38 2016 +0100
@@ -80,7 +80,7 @@
      * \param irccd the irccd instance
      * \param plugin the plugin
      */
-    virtual void load(Irccd &irccd, JsPlugin &plugin)
+    virtual void load(Irccd &irccd, std::shared_ptr<JsPlugin> plugin)
     {
         util::unused(irccd, plugin);
     }
--- a/libirccd-js/irccd/plugin-js.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/libirccd-js/irccd/plugin-js.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -450,7 +450,7 @@
         for (const auto &mod : m_modules) {
             log::debug() << "plugin " << plugin->name() << ": ";
             log::debug() << "loading " << mod->name() << " Javascript API" << std::endl;
-            mod->load(m_irccd, *plugin);
+            mod->load(m_irccd, plugin);
         }
 
         return plugin;
--- a/tests/js-elapsedtimer/main.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/tests/js-elapsedtimer/main.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -37,8 +37,8 @@
     TestElapsedTimer()
         : m_plugin(std::make_shared<JsPlugin>("empty", SOURCEDIR "/empty.js"))
     {
-        IrccdModule().load(m_irccd, *m_plugin);
-        ElapsedTimerModule().load(m_irccd, *m_plugin);
+        IrccdModule().load(m_irccd, m_plugin);
+        ElapsedTimerModule().load(m_irccd, m_plugin);
     }
 };
 
--- a/tests/js-file/main.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/tests/js-file/main.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -36,8 +36,8 @@
     TestJsFile()
         : m_plugin(std::make_shared<JsPlugin>("empty", SOURCEDIR "/empty.js"))
     {
-        IrccdModule().load(m_irccd, *m_plugin);
-        FileModule().load(m_irccd, *m_plugin);
+        IrccdModule().load(m_irccd, m_plugin);
+        FileModule().load(m_irccd, m_plugin);
     }
 };
 
--- a/tests/js-irccd/main.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/tests/js-irccd/main.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -34,7 +34,7 @@
     TestJsIrccd()
         : m_plugin(std::make_shared<JsPlugin>("empty", SOURCEDIR "/empty.js"))
     {
-        IrccdModule().load(m_irccd, *m_plugin);
+        IrccdModule().load(m_irccd, m_plugin);
     }
 };
 
--- a/tests/js-logger/main.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/tests/js-logger/main.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -63,9 +63,9 @@
     TestJsLogger()
         : m_plugin(std::make_shared<JsPlugin>("test", SOURCEDIR "/empty.js"))
     {
-        IrccdModule().load(m_irccd, *m_plugin);
-        PluginModule().load(m_irccd, *m_plugin);
-        LoggerModule().load(m_irccd, *m_plugin);
+        IrccdModule().load(m_irccd, m_plugin);
+        PluginModule().load(m_irccd, m_plugin);
+        LoggerModule().load(m_irccd, m_plugin);
     }
 };
 
--- a/tests/js-system/main.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/tests/js-system/main.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -37,9 +37,9 @@
     TestJsSystem()
         : m_plugin(std::make_shared<JsPlugin>("empty", SOURCEDIR "/empty.js"))
     {
-        IrccdModule().load(m_irccd, *m_plugin);
-        FileModule().load(m_irccd, *m_plugin);
-        SystemModule().load(m_irccd, *m_plugin);
+        IrccdModule().load(m_irccd, m_plugin);
+        FileModule().load(m_irccd, m_plugin);
+        SystemModule().load(m_irccd, m_plugin);
     }
 };
 
--- a/tests/js-timer/main.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/tests/js-timer/main.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -16,57 +16,62 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-int main() { }
-
-#if 0
-
 #include <gtest/gtest.h>
 
 #include <irccd/elapsed-timer.hpp>
 #include <irccd/irccd.hpp>
 #include <irccd/logger.hpp>
+#include <irccd/mod-irccd.hpp>
+#include <irccd/mod-plugin.hpp>
+#include <irccd/mod-timer.hpp>
 #include <irccd/plugin-js.hpp>
 #include <irccd/service.hpp>
 #include <irccd/system.hpp>
 
 using namespace irccd;
 
-TEST(Basic, single)
+class TestJsTimer : public testing::Test {
+protected:
+    Irccd m_irccd;
+    std::shared_ptr<JsPlugin> m_plugin;
+
+    void open(const std::string &file)
+    {
+        m_plugin = std::make_shared<JsPlugin>("timer", file);
+
+        IrccdModule().load(m_irccd, m_plugin);
+        PluginModule().load(m_irccd, m_plugin);
+        TimerModule().load(m_irccd, m_plugin);
+
+        m_plugin->onLoad(m_irccd);
+        m_irccd.plugins().add(m_plugin);
+    }
+};
+
+TEST_F(TestJsTimer, single)
 {
-    Irccd irccd;
+    open(IRCCD_TESTS_DIRECTORY "/timer-single.js");
+
     ElapsedTimer timer;
 
-    auto plugin = std::make_shared<JsPlugin>("timer", IRCCD_TESTS_DIRECTORY "/timer-single.js");
-
-    plugin->onLoad(irccd);
-    irccd.plugins().add(plugin);
+    while (timer.elapsed() < 3000)
+        util::poller::poll(512, m_irccd);
 
-    while (timer.elapsed() < 3000) {
-        util::poller::poll(512, irccd);
-        irccd.dispatch();
-    }
-
-    ASSERT_TRUE(duk_get_global_string(plugin->context(), "count"));
-    ASSERT_EQ(1, duk_get_int(plugin->context(), -1));
+    ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "count"));
+    ASSERT_EQ(1, duk_get_int(m_plugin->context(), -1));
 }
 
-TEST(Basic, repeat)
+TEST_F(TestJsTimer, repeat)
 {
-    Irccd irccd;
+    open(IRCCD_TESTS_DIRECTORY "/timer-repeat.js");
+
     ElapsedTimer timer;
 
-    auto plugin = std::make_shared<JsPlugin>("timer", IRCCD_TESTS_DIRECTORY "/timer-repeat.js");
-
-    plugin->onLoad(irccd);
-    irccd.plugins().add(plugin);
+    while (timer.elapsed() < 3000)
+        util::poller::poll(512, m_irccd);
 
-    while (timer.elapsed() < 3000) {
-        util::poller::poll(512, irccd);
-        irccd.dispatch();
-    }
-
-    ASSERT_TRUE(duk_get_global_string(plugin->context(), "count"));
-    ASSERT_GE(duk_get_int(plugin->context(), -1), 5);
+    ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "count"));
+    ASSERT_GE(duk_get_int(m_plugin->context(), -1), 5);
 }
 
 #if 0
@@ -105,5 +110,3 @@
 
     return RUN_ALL_TESTS();
 }
-
-#endif
--- a/tests/js-unicode/main.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/tests/js-unicode/main.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -39,8 +39,8 @@
     TestJsUnicode()
         : m_plugin(std::make_shared<JsPlugin>("empty", SOURCEDIR "/empty.js"))
     {
-        IrccdModule().load(m_irccd, *m_plugin);
-        UnicodeModule().load(m_irccd, *m_plugin);
+        IrccdModule().load(m_irccd, m_plugin);
+        UnicodeModule().load(m_irccd, m_plugin);
     }
 };
 
--- a/tests/js-util/main.cpp	Mon Nov 14 13:11:16 2016 +0100
+++ b/tests/js-util/main.cpp	Mon Nov 14 13:32:38 2016 +0100
@@ -35,8 +35,8 @@
     TestJsUtil()
         : m_plugin(std::make_shared<JsPlugin>("empty", SOURCEDIR "/empty.js"))
     {
-        IrccdModule().load(m_irccd, *m_plugin);
-        UtilModule().load(m_irccd ,*m_plugin);
+        IrccdModule().load(m_irccd, m_plugin);
+        UtilModule().load(m_irccd, m_plugin);
     }
 };