Register builtin extensions via a macro, rather than a manual strcmp
authorPaul Querna <pquerna@apache.org>
Wed, 14 Jul 2010 06:22:41 +0000 (23:22 -0700)
committerRyan Dahl <ry@tinyclouds.org>
Wed, 14 Jul 2010 17:17:25 +0000 (10:17 -0700)
Set the stage for making the builtin modules more dynamic.

Note: this only converts crypto and net, I will add more extensions in a
later commit.

* node.h: Add utility macro for converting macro values to strings.

* node.h: Include the actual module name inside the module structure, not
  just the file it was built from.

* node.h: New Macro, NODE_MODULE_DECL, for declaring an external reference
  to a module structure.

* node_extensions.cc: New File, implements get_builtin_module, which
  iterates over the module structures that are compiled into node.

* node.cc(node::Binding): Use the new module lookup function to find
  modules.

* node_{net,crypto}.c: Add NODE_MODULEs to generate the module structure.

src/node.cc
src/node.h
src/node_crypto.cc
src/node_extensions.cc [new file with mode: 0644]
src/node_extensions.h [new file with mode: 0644]
src/node_net.cc
wscript

index 6b697d3f3e79f3a8b87e93ca14bc09743765f2b1..e5ec939c410be9323980f77de25823f7dca05d3a 100644 (file)
@@ -1571,6 +1571,7 @@ static Handle<Value> Binding(const Arguments& args) {
 
   Local<String> module = args[0]->ToString();
   String::Utf8Value module_v(module);
+  node_module_struct* modp;
 
   if (binding_cache.IsEmpty()) {
     binding_cache = Persistent<Object>::New(Object::New());
@@ -1578,9 +1579,15 @@ static Handle<Value> Binding(const Arguments& args) {
 
   Local<Object> exports;
 
-  // TODO DRY THIS UP!
-
-  if (!strcmp(*module_v, "stdio")) {
+  if (binding_cache->Has(module)) {
+    exports = binding_cache->Get(module)->ToObject();
+  }
+  else if ((modp = get_builtin_module(*module_v)) != NULL) {
+    exports = Object::New();
+    modp->register_func(exports);
+    binding_cache->Set(module, exports);
+  }
+  else if (!strcmp(*module_v, "stdio")) {
     if (binding_cache->Has(module)) {
       exports = binding_cache->Get(module)->ToObject();
     } else {
@@ -1623,15 +1630,6 @@ static Handle<Value> Binding(const Arguments& args) {
       binding_cache->Set(module, exports);
     }
 
-  } else if (!strcmp(*module_v, "net")) {
-    if (binding_cache->Has(module)) {
-      exports = binding_cache->Get(module)->ToObject();
-    } else {
-      exports = Object::New();
-      InitNet(exports);
-      binding_cache->Set(module, exports);
-    }
-
   } else if (!strcmp(*module_v, "http_parser")) {
     if (binding_cache->Has(module)) {
       exports = binding_cache->Get(module)->ToObject();
@@ -1658,16 +1656,6 @@ static Handle<Value> Binding(const Arguments& args) {
       Buffer::Initialize(exports);
       binding_cache->Set(module, exports);
     }
-  #ifdef HAVE_OPENSSL
-  } else if (!strcmp(*module_v, "crypto")) {
-    if (binding_cache->Has(module)) {
-      exports = binding_cache->Get(module)->ToObject();
-    } else {
-      exports = Object::New();
-      InitCrypto(exports);
-      binding_cache->Set(module, exports);
-    }
-  #endif
   } else if (!strcmp(*module_v, "evals")) {
     if (binding_cache->Has(module)) {
       exports = binding_cache->Get(module)->ToObject();
index aec09557865e97f048138eb12f5fdc99255a5673..d879e4b236191c37a386fdaaf6b578c43e875a00 100644 (file)
 
 #include <node_object_wrap.h>
 
+#ifndef NODE_STRINGIFY
+#define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)
+#define NODE_STRINGIFY_HELPER(n) #n
+#endif
+
 namespace node {
 
 #define NODE_PSYMBOL(s) Persistent<String>::New(String::NewSymbol(s))
@@ -83,14 +88,16 @@ v8::Local<v8::Value> ErrnoException(int errorno,
 
 const char *signo_string(int errorno);
 
-
 struct node_module_struct {
   int version;
   void *dso_handle;
-  const char *name;
+  const char *filename;
   void (*register_func) (v8::Handle<v8::Object> target);
+  const char *modname;
 };
 
+node_module_struct* get_builtin_module(const char *name);
+
 /**
  * When this version number is changed, node.js will refuse
  * to load older modules.  This should be done whenever
@@ -108,9 +115,13 @@ struct node_module_struct {
   node::node_module_struct modname ## _module =    \
   {                                     \
       NODE_STANDARD_MODULE_STUFF,       \
-      regfunc                           \
+      regfunc,                          \
+      NODE_STRINGIFY(modname)           \
   };
 
+#define NODE_MODULE_DECL(modname) \
+  extern node::node_module_struct modname ## _module;
+
 
 }  // namespace node
 #endif  // SRC_NODE_H_
index ef314fa2ab94a6df9adfed5013b486ca7bc65be5..c16f66069893664affebb0e2c1c5e58cfb88fb3c 100644 (file)
@@ -2264,7 +2264,7 @@ void InitCrypto(Handle<Object> target) {
   version_symbol    = NODE_PSYMBOL("version");
 }
 
-
-
 }  // namespace node
 
+NODE_MODULE(node_crypto, node::InitCrypto);
+
diff --git a/src/node_extensions.cc b/src/node_extensions.cc
new file mode 100644 (file)
index 0000000..776bb40
--- /dev/null
@@ -0,0 +1,46 @@
+
+#include "node.h"
+#include "node_version.h"
+#include <string.h>
+
+#undef NODE_EXT_LIST_START
+#undef NODE_EXT_LIST_ITEM
+#undef NODE_EXT_LIST_END
+
+#define NODE_EXT_LIST_START
+#define NODE_EXT_LIST_ITEM NODE_MODULE_DECL
+#define NODE_EXT_LIST_END
+
+#include "node_extensions.h"
+
+#undef NODE_EXT_LIST_START
+#undef NODE_EXT_LIST_ITEM
+#undef NODE_EXT_LIST_END
+
+#define NODE_EXT_STRING(x) &x ## _module,
+#define NODE_EXT_LIST_START node::node_module_struct *node_module_list[] = {
+#define NODE_EXT_LIST_ITEM NODE_EXT_STRING
+#define NODE_EXT_LIST_END NULL};
+
+#include "node_extensions.h"
+
+namespace node {
+
+node_module_struct* get_builtin_module(const char *name)
+{
+  char buf[128];
+  node_module_struct *cur = NULL;
+  snprintf(buf, sizeof(buf), "node_%s", name);
+  /* TODO: you could look these up in a hash, but there are only 
+   * a few, and once loaded they are cached. */
+  for (int i = 0; node_module_list[i] != NULL; i++) {
+    cur = node_module_list[i];
+    if (strcmp(cur->modname, buf) == 0) {
+      return cur;
+    }
+  }
+
+  return NULL;
+}
+
+}; // namespace node
diff --git a/src/node_extensions.h b/src/node_extensions.h
new file mode 100644 (file)
index 0000000..f463a8c
--- /dev/null
@@ -0,0 +1,8 @@
+
+NODE_EXT_LIST_START
+NODE_EXT_LIST_ITEM(node_net)
+#ifdef HAVE_OPENSSL
+NODE_EXT_LIST_ITEM(node_crypto)
+#endif
+NODE_EXT_LIST_END
+
index 0e8ad819716c3f9eb937d6cad66a552342f2eb1c..1f2ae7ca4421d2bae24eec5e05196e8165030a54 100644 (file)
@@ -1266,3 +1266,5 @@ void InitNet(Handle<Object> target) {
 }
 
 }  // namespace node
+
+NODE_MODULE(node_net, node::InitNet);
diff --git a/wscript b/wscript
index d537fd1b5ad9d54f8e0b9be51682fa71911f375f..22152b0e059bb8ec1befe044baf33d5bbb06a799 100644 (file)
--- a/wscript
+++ b/wscript
@@ -459,6 +459,7 @@ def build(bld):
   node.source = """
     src/node.cc
     src/node_buffer.cc
+    src/node_extensions.cc
     src/node_http_parser.cc
     src/node_net.cc
     src/node_io_watcher.cc