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.
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());
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 {
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();
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();
#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))
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
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_
version_symbol = NODE_PSYMBOL("version");
}
-
-
} // namespace node
+NODE_MODULE(node_crypto, node::InitCrypto);
+
--- /dev/null
+
+#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
--- /dev/null
+
+NODE_EXT_LIST_START
+NODE_EXT_LIST_ITEM(node_net)
+#ifdef HAVE_OPENSSL
+NODE_EXT_LIST_ITEM(node_crypto)
+#endif
+NODE_EXT_LIST_END
+
}
} // namespace node
+
+NODE_MODULE(node_net, node::InitNet);
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